理解红黑树之JDK源码应用

一、红黑树的介绍

算法导论对红黑树的介绍:

红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。
通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的

二、红黑树的性质

  1. 每个结点要么是红的,要么是黑的。
  2. 根结点是黑的
  3. 定义NULL为黑色
  4. 如果某个子结点是红色的,那么它的两个儿子都是黑色的,且父结点也必定是黑色的。
  5. 对于任一个结点而言,它到叶结点的每一条路径都包含相同数目的黑色结点,称为黑高(BlackHight、BH)。

    正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度。N个结点的RBT,最大高度是2log(N+1)

    若H(left)>=H(right),则H(left)<=2*H(right)+1 但 BH(right) == BH(left)。

三、红黑树的旋转和变色。

    当对红黑树进行删除和插入操作时,就会对树的结构造成修改,从而会破坏红黑树的性质,所以当我们对红黑树进行删除或者插入操作时需要,调整树的结构使红黑树的性质不被破坏,可以通过对结点进行重新着色,以及对树进行相关的旋转操作,即通过修改树中某些结点的颜色及指针结构。

   1、旋转:

     

算法导论的代码:

LeftRoate(T, x)
y ← x.right				       //定义y:y是x的右孩子
x.right ← y.left	            //y的左孩子成为x的右孩子
if y.left ≠ T.nil
    y.left.p ← x	
y.p ← x.p				       //x的父结点成为y的父结点
if x.p = T.nil
	then T.root ← y
else if x = x.p.left
	then x.p.left ← y
else x.p.right ← y 
y.left ← x                       //x作为y的左孩子
x.p ← y

四、红黑树的插入

      插入原则:若插入的结点为黑色,则肯定违反性质5,则只能插入红色结点,可能违反性质4,继续调整。

     红黑树的插入调整:

  • 考虑到左子树的情况,规定如下标记
  1. 正在处理的结点X,也叫子结点
  2. 父结点P
  3. 爷爷结点G
  4. 叔叔结点Y
  5. A3表示黑高为3的红黑树

  •   无需调整的情况为:
  1. X为根结点,将X由红染黑,简称rootOver
  2. 父节点P为黑色,BlackParentOver,简称bpOver
  •    仅仅需要考虑父节点P为红色的情形,由于性质4,爷爷结点G必定是黑色,分为三种情况:
    • case1:Y为红色,X可左可右;P、Y染黑,G染红,X回溯至G
    • case2:Y为黑色,X为右孩子;左旋P,X指向P,转化为case3
    • case3:Y为黑色,X为左孩子;P染黑,G染红,右旋G,结束
  • 结论:RBT的插入调整最多旋转2次。
  • 先看一下无需调整的JDK源码:
    • 越界,X是根节点,父节点P的颜色为黑,必定满足性质4

             最后一步:将根节点root染黑

  • case1的源码
    • 条件:P为G的左孩子,Y为红色,X可左可右
    • 处理方式:P、Y染黑,G染红,X回溯之G
  • case2的源码
    • 条件:P为G的左孩子,Y为黑色,X为右孩子
    • 处理方式:右旋P,X指向P,转化为case3
  • case3的源码
    • 条件:P为G的左孩子,Y为黑色,X为左孩子
    • 处理方式:P染黑,G染红,左旋G,结束

 

五、红黑树的删除

      删除原则:删除红色结点,不会影响BH,也不会违反性质4,无需调整

     删除黑色结点,结点所在子树的BH--,需要调整

  • 考虑到删除左子树的情况,规定如下标记:
    1. 正在处理的结点X
    2. 父结点P
    3. 兄弟结点sib,简称S
    4. 左侄leftNephew,简称LN
    5. 右侄rightNephew,简称RN

  • 红黑树的删除调整
    • 需要删除的结点X为红色,直接删除X
    • 其他无需调整的情况为:
      1. 当前X为根节点,无论root什么颜色,都将root染黑,rootOver
      2. 当前X为红色,将X染黑,结束,redOve 
    • 删除左孩子X,分为四种情况:
      1. case1:S为红色;S染黑;P染红,左旋P
      2. case2:S为黑色;黑LN,黑RN;S染红,X回溯到P
      3. case3:S为黑色;红LN,黑RN;LN染黑,S染红,右旋S
      4. case4:黑S,LN随意,红RN;S变P的颜色,P和S染黑,左旋P
  • 删除的X本身就是红色节点,直接删除
  • 无需调整2
    • 回溯指针时遇到的情况:
      1. X为根节点,无论root什么颜色,都将root染黑,将根节点染黑同时满足2、4、5,简称rootOver
      2. X为红色,将X染黑,简称redOver
  • case1源码
    • 条件:S为红色
    • 由于性质4,P、LN、RN必定都为黑色
    • 处理方式:S染黑,P染红,左旋P,LN成为新的sib
  • case2源码:
    • 条件:S、LN、RN均为黑色,P为红色或者黑色
    • 处理方式:S染红,X回溯至P
  • case3源码:
    • 条件:S为黑色,LN为红色,RN为黑色
    • 处理方式:LN染黑、S染红、右旋S,S指向LN转化为case4
  • case4源码:
    • 条件:S为黑色,P可红可黑,RN为黑色
      • 处理方式:S的颜色设置为与P相同,P染黑,RN染黑,左旋P,X指向根节点,rootOver
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章