红黑树的理解说明(删除)
来源:互联网 发布:java 策略模式 编辑:程序博客网 时间:2024/05/16 12:39
红黑树5个性质
1、根节点是黑色的
2、每个节点不是黑色的就是红色的
3、叶子节点都是黑色的
4、如果一个节点是红色的,那么他的2个儿子都是黑色的
5、每个节点到叶子节点的每一条路径都包含相同数量的黑节
删除伪代码,伪代码来自:http://blog.csdn.net/v_july_v/article/details/6105630
- 1 if left[z] = nil[T] or right[z] = nil[T]
- 2 then y ← z
- 3 else y ← TREE-SUCCESSOR(z)
- 4 if left[y] ≠ nil[T]
- 5 then x ← left[y]
- 6 else x ← right[y]
- 7 p[x] ← p[y]
- 8 if p[y] = nil[T]
- 9 then root[T] ← x
- 10 else if y = left[p[y]]
- 11 then left[p[y]] ← x
- 12 else right[p[y]] ← x
- 13 if y ≠ z
- 14 then key[z] ← key[y]
- 15 copy y's satellite data into z
- 16 if color[y] = BLACK
- 17 then RB-DELETE-FIXUP(T, x)
- 18 return y
记住:y是要被删除的节点,y可能为z或者z的后继, x是y的儿子节点,x可能等于nil[T](非NULL),当y被删除后,x会替换到y的位置,这点对理解代码很重要
y被从树上断开(删除)后, 只有在y节点是黑色的时候,红黑树的属性:路径黑节点数相同,会发生变化:
if color[y] = BLACK
RB-DELETE-FIXUP(T, x)
y节点是红色的时候,删除y,红黑树的性质不会发生变化。
RB-DELETE-FIXUP(T, x) 的伪代码:
- 1 while x ≠ root[T] and color[x] = BLACK
- 2 do if x = left[p[x]]
- 3 then w ← right[p[x]]
- 4 if color[w] = RED
- 5 then color[w] ← BLACK ▹ Case 1
- 6 color[p[x]] ← RED ▹ Case 1
- 7 LEFT-ROTATE(T, p[x]) ▹ Case 1
- 8 w ← right[p[x]] ▹ Case 1
- 9 if color[left[w]] = BLACK and color[right[w]] = BLACK
- 10 then color[w] ← RED ▹ Case 2
- 11 x ← p[x] ▹ Case 2
- 12 else if color[right[w]] = BLACK
- 13 then color[left[w]] ← BLACK ▹ Case 3
- 14 color[w] ← RED ▹ Case 3
- 15 RIGHT-ROTATE(T, w) ▹ Case 3
- 16 w ← right[p[x]] ▹ Case 3
- 17 color[w] ← color[p[x]] ▹ Case 4
- 18 color[p[x]] ← BLACK ▹ Case 4
- 19 color[right[w]] ← BLACK ▹ Case 4
- 20 LEFT-ROTATE(T, p[x]) ▹ Case 4
- 21 x ← root[T] ▹ Case 4
- 22 else (same as then clause with "right" and "left" exchanged)
- 23 color[x] ← BLACK
进入正题,上面这段代码很简练,意思就是:
一、x是红色,比较容易办,由于删除了一个y是黑色,所以直接将x涂成黑色,即可保持红黑树的性质,只执行第23行即可
二、x是黑色,x是根节点,显然什么也不用干,这颗树还是红黑树,代码只执行第23行
三、x是黑色,x不是根节点,才执行do操作
进入case前,先理一下删除节点的代码,本来x=y.child,y被删除,x就替换到y的位置,那么原来通往x的路径上就少了一个黑节点,我们就想办法在这条路径上增加一个节点并涂黑色(通过旋转实现,旋转可以在某条路径上增加一个节点),或者在其他的路径(兄弟节点路径)上也修改一个节点的颜色(黑->红),来达到红黑树的路径黑节点数目相同的性质,原理是这样,为达目标也不是这么简单,具体通过以下case来实现。
先引用一张靓图,出自:http://blog.csdn.net/v_JULY_v/article/details/6109153
case1:x是黑色,x的兄弟w是红色
操作:
- color[w] ← BLACK ▹ Case 1
- color[p[x]] ← RED ▹ Case 1
- LEFT-ROTATE(T, p[x]) ▹ Case 1
- w ← right[p[x]] ▹ Case 1
由于在x处原来有个黑的y被删除,导致从B->A就少一个黑节点,再看兄弟节点D点是红色,B一定是黑色,所以没法直接通过改变颜色来维持红黑树的性质了,必须通过旋转来改变路径上的节点数才可能维持红黑性质,怎么旋呢?旋转x的父节点,而且往删除节点的方向去旋转,这样旋转后在删除的那个方向的路径上会多一个节点,然后将多出的节点着一个黑色,就可以使这个路径上的黑节点数平衡,但是可能在旋转点的另一路径上会破坏平衡,所以需要在调整节点后继续循环处理。
1、先考虑直接左旋转B点,旋转后B->C黑节点数未变,但是D->E路径黑节点数会少1,所以不行,而且D节点为红色,旋转后可能会与D的父节点颜色冲突。
2、所以先将D变黑,再旋转,旋转后就不会导致与性质4冲突,D变黑,D节点(黑色)与其父节点的颜色就不会冲突,而且旋转后从D到X节点的黑节点数也恢复到删除前的数量了,但是,仔细看看D->C的路径上黑节点数,多了一个,所以还需要继续往下处理。
3、为了维持性质5,接下来要么将B涂红,要么将C涂红,能将C涂红吗?目测好像可以,但是改变C的颜色后又要判断C的儿子节点是不是红的,如此下去,过于麻烦了。
4、所以将B涂红,将B涂红,与C的颜色不冲突。而且这样会将树转换为了case2或者case3或者case4的状态了,将B涂红后,D到X节点路径的黑节点又回到了删除状态时的样子(即少一个黑节点数),故继续进入其他case。
5、w ← right[p[x]] 加上这句就可以不用循环就直接其他case(因为w是黑的),去掉这句然代码多循环一次,进入其他case也行。
综上说明,case1操作后仅仅是在删除节点的路径上增加了一个红节点(意味着在这条路径上图黑一个节点就可以达到黑节点数平衡),并未恢复红黑树的性质5,黑节点数和未调整时时一样的(比删除前原树小1),经过这次调整后树状态转换为case2或者case3或者case4。
case2,x是黑色,x的兄弟w是黑色,并且兄弟的2子均为黑色
显然,将x的兄弟的黑图成红,即可在兄弟路径上的黑节点数减少一个,达到与x路径的黑节点数一致(由于删除的y是黑色),但是这个调整可能破环性质4(x的父是红色时),故修改x为x的父,再次进入循环,进入循环后,如果x原来是红色,则执行23行,将x图黑(+1黑),即恢复了所有红黑性质,退出;如果x为黑色,需要继续处理直到将黑节点数的性质恢复,这个时候可能进入任何一个case。
case3,x是黑色,x的兄弟w是黑色,并且兄的右子为黑色(左子一定是红色)
先来直接图色看能不能恢复黑节点数性质,显然需要将D图红,D的左子C必须图黑,那么B->E黑节点数少一个将与X路径上一致,但是B->C路径的黑节点数未变化,故以D节点来一次右旋,由于此时C为黑色,D为红色,所有在在B的右孩子的所有路径上的所有黑节点数与进行case操作前是一致的,这样做的好处就是在B的右边孩子路径上会多一个节点,为case4的左旋(为B的左孩子多一个节点)打下了基础;仔细观察,这次操作后,树状图转换为了case4。
case4,x是黑色,x的兄弟w是黑色,并且兄的右子为红色(左子颜色不定)
这个直接进行一次如下操作
- color[w] ← color[p[x]] ▹ Case 4
- color[p[x]] ← BLACK ▹ Case 4
- color[right[w]] ← BLACK ▹ Case 4
- LEFT-ROTATE(T, p[x]) ▹ Case 4
D->A黑节点数多一,和删除y以前的数量一致
D->C,D->E的黑节点数未变化
总结:删除的修复主要是在删除节点的路径上通过旋转来增加一个节点,然后再在这条路径上图黑一个节点,就修复了由于删除一个黑节点而引起的黑节点数不平衡的性质破环。
- 红黑树的理解说明(删除)
- 红黑树的理解说明(插入)
- 我所理解的红黑树删除
- 理解红黑树的节点插入和删除
- hibernate删除的理解
- 理解红黑树(下)删除操作
- 红黑树理解-插入删除
- C++前置说明的理解
- chmod的使用理解说明
- 学习型工厂模式构建的理解(代码说明)
- 小波变换轻松入门(我的理解说明)
- hashMap的一点理解,画图说明(初始16 /.75)
- datagridview删除行的理解
- 教你真正理解红黑树的删除原理
- DPInst中关于删除的说明
- 关于文章被删除的说明
- 关于spring中aop的理解和说明(个人理解)
- __proto__和prototype的理解(谈区别说明你没有理解)
- Git 简单使用
- C语言tips
- iOS开发,更改状态栏(StatusBar)文字颜色为白色
- STD 2015 hdu5317 打表预处理
- 畅通工程
- 红黑树的理解说明(删除)
- 57. Insert Interval
- 解题笔记(30)——找含单链表的环入口点(转网上某位高手的解法)
- Atom飞行手册翻译: 1.4 小结
- 写在Demo战斗系统之前,先用原型工具做套UI第三篇-常规UI界面制作
- linux上安装SVN
- HDU 2120--Ice_cream's world I【并查集, 判断环的个数】
- 传智播客承办工信部CSIP全国骨干教师暑期研修班
- 关于中文插入mysql 乱码(unicode十进制编码)问题