红黑树的原理和实现

二叉树的缺陷,退化成链表的时候,几乎成为线性,不平衡,从而诞生了红黑树

红黑树

满足二叉树的基本特性,同时还有下面的特性:

  1. 节点是红色或是黑色的
  2. 根节点是黑色的
  3. 每个叶子的节点都是黑色的(NIL节点)
  4. 红色节点的两个子节点都是黑色(不能有连续的红色节点)
  5. 任意节点到叶子节点的所有路径都包含相同数目的黑色节点

从而保证了红黑树的自平衡,红黑树从根到叶子的最长路径不会超过最短路径的两倍。

插入和删除节点的时候,红黑树的规则有可能被打破,如下图:

 

因此,需要变色和旋转

变色

插入21,两个红色节点不能相连,22变成黑色。

两个黑色节点不能相连,25变成红色。

此时仍然没有结束,因为节点25和节点27又形成了两个连续的红色节点,需要继续把节点27从红色变成黑色:

左旋转:

逆时针旋转红黑树的两个节点,使得父节点被自己的右孩子取代,而自己成为自己的左孩子。说起来很怪异,大家看下图:

右旋转:

顺时针旋转红黑树的两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子。大家看下图:

何时用旋转?

旋转成

由于根节点必须是黑色节点,所以需要变色,变色结果如下:

这样就结束了吗?并没有。因为其中两条路径(17 -> 8 -> 6 -> NIL)的黑色节点个数是4,其他路径的黑色节点个数是3,不符合规则5。

这时候我们需要把节点13看做X,节点8看做Y,像刚才的示意图那样进行右旋转

最后根据规则来进行变色

如此一来,我们的红黑树变得重新符合规则。这一个例子的调整过程比较复杂,经历了如下步骤:

变色 -> 左旋转 -> 变色 -> 右旋转 -> 变色

应用

TreeMap和TreeSet都用到了红黑树,Java8中的HashMap也用到红黑树

猜你喜欢

转载自blog.csdn.net/weixin_39203720/article/details/114381878