数据结构(二)--- 红黑树

1、简述

红黑树是一种特殊的二叉树,而且是优秀的自平衡查找树,下图为红黑树的示例:html

红黑树具备如下几大特性:算法

一、根节点为黑色。网络

二、全部节点都是黑色或红色。性能

三、全部叶子节点(Null)都是黑色。学习

四、红色节点的子节点必定是黑色的。spa

五、任意一个节点到其叶子节点的全部路径上的黑色节点数量相同(黑色完美平衡二叉树)。设计

以上的五大特定也是维持红黑树结构的基本规则,可是明白了这些规则,不表明咱们就明白了红黑树的设计原理及规则维持算法。指针

在咱们平常的工做中多多少少都会接触到红黑树,特别是JDK1.8以后hashmap的底层采用了红黑树机构,接下来的博文中咱们会一点点弄明白如下几个问题,也是笔者在学习以前不明白的两个问题:htm

一、红黑树为何要维持自平衡、自平衡的好处是什么?blog

二、什么是左旋,右旋,变色?

三、什么条件下须要进行左旋、右旋、变色?

2、红黑树的自平衡

根据上一节红黑树特性第5点能够知道,红黑树是一颗黑色完美平衡二叉树,红黑树从根节点到叶子结点的最长路径不会超过最短路径的2倍

这就保证了红黑树优秀的查找性能,其查找的时间复杂度为O(logn);

当插入或删除阶段操做过程当中,会破坏此平衡结构,当平衡遭到破坏,程序会进行一系列操做来从新维持平衡,这一过程就是自平衡;这一系列操做就是左旋、右旋、变色。 

一、左旋:

对当前节点进行左旋:当前节点的右子节点变为父节点,原右子节点的左子节点变为当前节点的右子节点,如图演示(对150节点进行左旋):

上图对150节点左旋:

  1. 把150节点的右子节点170变为其父节点(170变为150的父节点)。
  2. 把150节点的原右子节点170的左子节点160变为其右子节点(160变为150的右子节点)。

注意:

    • 图中只是示意图,在第一步以后,170节点并无三个指向其余节点的指针,这里只是为了理解起来更清晰
    • 图中只是进行左旋,尚未涉及变色问题,因此会看到父节点与子节点同色问题。
    • 左旋操做涉及到的节点只是当前节点的右子节点和右子节点的左子节点两个节点,其余节点不变。

二、右旋:

对当前节点进行右旋:当前节点的左子节点变为父节点,原左子节点的右子节点变为当前节点的左子节点,如图演示(对150节点进行右旋):

上图对150节点进行右旋:

  1. 把150节点的左子节点130变为其父节点(130变为150的父节点)。
  2. 把150节点的原左子节点130的右子节点null节点变为其左子节点(130的原右子节点null变为150的左子节点)。

 注意:

    • 图中只是示意图,在第一步以后,130节点并无三个指向其余节点的指针,这里只是为了理解起来更清晰
    • 图中只是进行左旋,尚未涉及变色问题,因此会看到父节点与子节点同色问题。
    • 右旋操做涉及到的节点只是当前节点的左子节点和左子节点的右子节点两个节点,其余节点不变。

三、变色:

节点的变色:就是节点由红色变成黑色或有黑色变成红色。

而在实际的维持自平衡的过程当中变色过程有多是一个连锁反应,而破坏平衡结果的操做有插入和删除。 

3、节点的插入

红黑树新节点的插入有可能会破坏现有的平衡结构,因此就须要进行节点的变色、左旋或者右旋操做来保持红黑树的平衡;但插入操做的状况区分比较多,这也正是红黑树自平衡结构不容易理解的地方之一;

下图就是插入的全部状况,接下来会有针对每种状况进行详细讲解:

其余3种状况很是简单,这里详细说明第四种状况:

C - current 当前节点,P - parent 父节点,PP - 祖父节点,U - uncle 叔叔节点, O - 其余节点 

状况四、P 为红色

4.一、P 为红色且 U 为红色 (如图 4.1)

(1)将 P 设为黑色

(2)将 U 设为黑色

(3)将 PP 设为红色

(4)将 PP 设为当前节点(这时 PP 就为 C 节点了),重复状况4判断

 

 

4.二、P 为红色且 U 不存在或为黑色 

4.2.一、P 是左节点,C 左节点 (P 为红色且 U 不存在或为黑色)(如图4.2.1)

(1)将 P 设为黑色

(2)将 PP 设为红色

(3)对 PP 进行右旋

 

4.2.二、P 是左节点,C 右节点 (P 为红色且 U 不存在或为黑色)(如图4.2.2)

(1)对 P 进行左旋

(2)设 PP 为当前节点

(3)此时结构变为 4.2.1 结构,继续进行 4.2.1 操做

 

4.2.三、P 是右节点,C 右节点 (P 为红色且 U 不存在或为黑色)(如图4.2.3)

(1)将 P 设为黑色

(2)将 PP 设为红色

(3)对 PP 进行左旋

4.2.四、P 是右节点,C 左节点 (P 为红色且 U 不存在或为黑色)(如图4.2.4)

(1)对 P 进行右旋

(2)设 PP 为当前节点

(3)此时结构变为 4.2.3 结构,继续进行 4.2.3 操做

 

节点插入总结:

    • 当前节点(新插入的节点)会在旋转变色以前就设置为红色;为何插入节点为红色?由于根据红黑树的特性,当父节点为黑色时,不须要作自平衡操做,若是为黑色,那么插入后褐色层次增长了,破坏特性5。
    • 在4.1状况中(P为红色且U为红色)若是重复递归判断到根节点,把根节点设置成了红色,则根据特性1,必须把根节点变回黑色,此时红黑树的黑色节点层次就增长了一层(自底向上生长)。

 4、节点的删除

红黑树的节点插入比较复杂,删除操做更加复杂,但掌握了规律理解起来就简单多了;

说到节点删除以前,须要先了解一下前继节点和后继节点的概念,笔者学习过程当中看到一个很是容易理解的描述,以下图:

把全部的节点投射到X轴上,这时全部的节点都是自左至右排好的,这样某个节点的左边的节点就是它的前继节点,右边的节点就是它的后继节点。

由上图能够看到,后继节点是右子树的最左节点,前继节点是左子树的最右节点。

如150节点的前继节点就是130,后继节点就是160。

节点删除后空出的位置须要找到其后继节点或前继节点进行补位,若是被删除的节点没有子节点还好,要是有子节点,不补位的话树就散了;而且补位以后有可能会破坏红黑树的平衡结构,这时就须要进行自平衡了。

因此节点的删除过程能够理解为寻找后继节点或前继节点(通常习惯用后继几点)进行补位后进行自平衡的过程;这样理解,节点删除问题就能够转换为补位节点(后继节点)的问题,补位完成后节点的颜色变为被删除的颜色

而这一结果再简单就能够理解为:补位节点后继节点)的删除的自平衡问题,后继节点老是在树的最底层。

这样一来就能够区分补位节点的几种状况:

 

R - replace 补位节点,P - parent 父节点,PP - 祖父节点,B - brother 兄弟节点,BL - brother left 兄弟节点左子节点,BR - brother right 兄弟节点右子节点, O - 其余节点 

状况1: R 为红色

状况1比较简单,红色节点不影响红黑树的自平衡结构,因此直接补位,并把颜色转换为被删除节点的颜色。

状况2: R 为黑色

2.一、R 为左子节点

2.1.一、R 为黑色且为左子节点,B 为红色(如图 2.1.1)

(1)、将 B 设为黑色
(2)、将 P 设为红色
(3)、对 P 进行左旋,获得 2.1.2.3 状况
(4)、按照 2.1.2.3 状况进行处理

2.1.二、R 为黑色且为左子节点,B 为黑色

2.1.2.一、R 为黑色且为左子节点,B 为黑色,BR 为红色,BL 为任意(如图 2.1.2.1)

(1)、将 B 设为 P 的颜色
(2)、将 P 设为黑色
(3)、将 BR 设为黑色
(4)、对 P 进行左旋

在此处有几个问题,注意上图框出的部分

一、为何此处不符合自平衡结构?

回答:节点的删除是先找到补位节点(后继节点),而后自平衡处理,而后才进行补位,因此此处的 R 以后会移走的,因此仍是符合自平衡结构。

二、BL 可能为黑色节点么?

回答:BL 不可能为黑色节点,但其可能为黑色叶子节点(NULL节点),下边用穷举法进行证实;

咱们知道,在节点删除以前(第一次删除),红黑树是保持平衡结构的,那么若是 BL 为黑色,那么有一下几种状况:

1)P 为黑色,BL 为黑色,以下图(1),不平衡,不成立

2)P 为红色,BL 为黑色,以下图(2),不平衡,不成立

3)P 为红色,BL 为黑色叶子节点(NULL),以下图(3),平衡,成立

4)P 为黑色,BL 为黑色叶子节点(NULL),以下图(4),平衡,成立

5)BL 为红色,以下图(5),平衡,成立

综上:BL 只可能为红色节点或黑色叶子节点(NULL)。

2.1.2.二、R 为黑色且为左子节点,B 为黑色,BR 为黑色,BL 为红色(如图 2.1.2.2)

(1)、将 B 设为红色
(2)、将 BL 设为黑色
(3)、对 B 进行右旋,获得 2.1.2.1 状况
(4)、按照 2.1.2.1 状况进行处理

  

2.1.2.三、R 为黑色且为左子节点,B 为黑色,BR 为黑色(NULL),BL 为黑色(NULL)(如图 2.1.2.3)

(1)、将 B 设为红色
(2)、将 P 做为新的补位节点
(3)、从新进行删除节点处理

 

须要注意:

    • 这时 P 就是 将要被移走的 R 的补位节点(后继节点)。
    • 此种状况下其实 BL,BR 都是黑色的叶子节点(NULL)。
    • B 变为红色是的缘由是整颗子树都是黑色的节点,R 移走后,不管如何操做都没办法在子树内自平衡,因此,最简单的操做把 B 变为红色,这样就自平衡了;可是这样一来 子树内部的黑色节点层数少了一层,这样从 P 子树的上一层数来看就是不平衡的了,因此要将 P 当作新的补位节点,进行自平衡操做,自底向上,直至根节点。

2.二、R为右子节点

2.2.一、R 为黑色且为右子节点,B 为红色(如图 2.2.1)

(1)、将 B 设为黑色
(2)、将 P 设为红色
(3)、对 P 进行右旋,获得 2.2.2.3 状况
(4)、按照 2.2.2.3 状况进行处理

2.2.二、R 为黑色且为右子节点,B 为黑色

2.2.2.一、R 为黑色且为右子节点,B 为黑色,BL 为红色,BR 为任意(如图 2.2.2.1)

(1)、将 B 设为 P 的颜色
(2)、将 P 设为黑色
(3)、将 BL 设为黑色
(4)、对 P 进行右旋

注意:

此种状况请参考 2.1.2.1中的问题与回答。 

2.2.2.二、R 为黑色且为右子节点,B 为黑色,BL 为黑色,BR 为红色(如图 2.2.2.2)

(1)、将 B 设为红色
(2)、将 BR 设为黑色
(3)、对 B 进行左旋,获得 2.2.2.1 状况
(4)、按照 2.2.2.1 状况进行处理

 

2.2.2.三、R 为黑色且为右子节点,B 为黑色,BL 为黑色(NULL),BR 为黑色(NULL)(如图 2.2.2.3)

(1)、将 B 设为红色
(2)、将 P 做为新的补位节点
(3)、从新进行删除节点处理

 

须要注意:

参考 2.1.2.3 下方的须要注意说明

节点删除总结:

  1. 节点的删除状况比较多,但左右子节点状况是对称的,理解了其中一种,另外一种也很快会理解。
  2. 补位节点能够用前继节点代替,也能够用后继节点代替,通常习惯用后继节点。
  3. 节点删除过程是先找到补位节点,而后进行自平衡处理,而后才会移除补位节点,即带补位节点的自平衡。
  4. 在全黑节点的状况下,可能发相似递归的生自底向上的寻找补位节点的过程,到根节点为止。
  5. 自平衡的顺序能够理解为,先本身处理,处理不了找兄弟节点参与,还处理不了找父节点参与,还处理不了让父节点找父节点的兄弟处理,以此类推。

5、红黑树总结 

经过上边对红黑树的详细谅解,咱们就能够回答开始提出的问题了。

一、红黑树为何要维持自平衡、自平衡的好处是什么?

答:红黑树是一个高效的查询树,保持平衡结构,能够保证从根节点到叶子节点的最长路径不超过最短路径的两倍,能够保证查询效率。

二、什么是左旋,右旋,变色?

答:左旋、右旋、变色都是对节点所在子树的操做,以节点为基进行变化保持树的平衡的操做。

三、什么条件下须要进行左旋、右旋、变色?

答:当发生节点插入或删除操做时,红黑树的平衡被破坏,这是就要根据具体的状况进行自平衡操做,即左旋、右旋或变色。

  • 红黑树的结构比较复杂,不管是节点的插入仍是删除,都有可能破坏自平衡结构,而自平衡过程最复杂状况多是自底向上处理,直到根节点。
  • 红黑树是平衡二叉树,但不是完美的平衡二叉树,只是黑色完美的平衡二叉树(性质5)
  • 红黑树的五条性质任意一套被破坏都触发自平衡操做。
  • 红色节点的子节点必定是黑色,但黑色节点的子节点则能够是红色和黑色任意一种,便可以有相邻的两层节点都是黑色的状况,如图:

 

 

 此博客为笔者参考网络上各种文章总结性书写,原创手打,若有错误欢迎指正。

原文出处:https://www.cnblogs.com/MouseDong/p/11276211.html

相关文章
相关标签/搜索