红黑树的理解说明(插入)
来源:互联网 发布:淘宝卖家从哪里登陆 编辑:程序博客网 时间:2024/06/01 07:26
本博客很多地方都是引自http://blog.csdn.net/v_july_v/article/details/6105630,算是对这篇博客的一个补充吧。
首先先来看一下红黑树5个性质
1、根节点是黑色的
2、每个节点不是黑色的就是红色的
3、叶子节点都是黑色的
4、如果一个节点是红色的,那么他的2个儿子都是黑色的
5、每个节点到叶子节点的每一条路径都包含相同数量的黑节
在插入或者删除节点后,为了保持这5个性质不变,需要做2件事就行了:
1、更改一些节点的颜色
2、交换节点的位置(目的也是为了修改颜色,同时可以使某条路径的红或者黑节点的数量发生改变,书上说的左、右旋)
一、插入
1、插入节点的颜色着为红色(为什么不着为黑色?性质5被破坏)
引用一片博客的伪代码(http://blog.csdn.net/v_july_v/article/details/6105630)
- RB-INSERT-FIXUP(T, z)
- while z.p.color == RED
- do if z.p == z.p.p.left
- then y ← z.p.p.right
- if y.color == RED
- then z.p.color ← BLACK ▹ Case 1
- y.color ← BLACK ▹ Case 1
- z.p.p.color ← RED ▹ Case 1
- z ← z.p.p ▹ Case 1
- else if z == z.p.right
- then z ← z.p ▹ Case 2
- LEFT-ROTATE(T, z) ▹ Case 2
- z.p.color ← BLACK ▹ Case 3
- z.p.p.color ← RED ▹ Case 3
- RIGHT-ROTATE(T, z.p.p) ▹ Case 3
- else (same as then clause with "right" and "left" exchanged)
- T.root.color ← BLACK
- 首先请记住插入节点的颜色为红色
- 如果插入节点的父节点为黑色是不会改变红黑树性质,只有插入节点的父节点也是红色的情况下才需要做调整来维持树的性质。
case1:插入节点的父节点红色,叔叔节点红色
操作:
- z.p.color ← BLACK ▹ Case 1
- z.p.p.color ← RED ▹ Case 1
- y.color ← BLACK ▹ Case 1
父节点为红色,那么连续2个红色,违反了性质4,必须设置父节点为黑色才不违反性质4,父节点的颜色由红变黑,变化后在这条路径上的黑节点数就多了一个(+1黑),怎么办?继续往上将祖父节点由原来的黑色(一定是黑色)变为红色,变化后在这条路径上的黑节点数就少了一个(-1黑),经过这2次(+1黑和-1黑)变化颜色,这条路径上的黑节点数还是没有变化,这就保持了性质5,祖父节点由黑变为了红,那么通往他叔叔节点的路径上的黑颜色节点数量就少了一个(-1黑),怎么办?将叔叔节点的红色变为黑色(+1黑),也就全部维持了性质5了。
综合上面的说明,个人觉得伪代码应该这么写,会更容易理解(调换case1标注的2、3行)
- z.p.color ← BLACK ▹ Case 1
- z.p.p.color ← RED ▹ Case 1
- y.color ← BLACK ▹ Case 1
z ← z.p.p ▹ Case 1
将当前节点设置到祖父节点,重新进入while循环进行处理,每循环一次,将会将z节点以下的这段树恢复红黑性质,如此这样一段一段往上处理,直到while循环退出,树的性质都被恢复。
case2:插入节点的父节点红色,叔叔节点黑色,当前节点为父节点的右孩子
操作:
- z ← z.p ▹ Case 2
- LEFT-ROTATE(T, z) ▹ Case 2
为什么要以父节点先进行左旋?单独进行着色的改变能维持性质吗,我们来试一下,先看祖孙的颜色,当前节点红色,父节点红色,祖父节点黑色。
1、首先必须将父节点涂成黑色,那么路径上就多了一个黑色(+1黑)
2、必须将祖父节点涂成红色(-1黑)才能维持性质5
3、祖父涂成红色,那么通往当前节点的叔叔节点的那条路径上就会少了一个黑色,违反了性质5
4、能继续往祖父的父节点一直往上修改颜色来达到性质5的维持吗?答案是不行的,仔细想想,在修改祖父节点颜色后,通往自己的这一条路径上黑颜色节点数量维持了,而通往叔叔那条路径上的黑节点数少了一个,为了维持叔叔路径上的黑节点数量,必须要增加祖宗节点上的黑节点数量,这又导致了通往自己的路径上的黑节点数量不能维持(+1黑)
5、第4步走不通,走另外一种方法,改为右旋祖父节点,这时候可以修复性质5,但是右旋后,右边子树的性质4被破坏(可以自己画图旋转下,祖父节点红,祖父的左子(即当前节点)也为红)
所以我们要用另外一个办法,就是先旋转,先左旋后进入case3,在case3里再做上面这些操作,就能神奇的同时恢复性质4和性质5(精妙!)。
case3:插入节点的父节点是红色,叔叔节点黑色,当前节点为父节点的左孩子
操作:
- z.p.color ← BLACK ▹ Case 3
- z.p.p.color ← RED ▹ Case 3
- RIGHT-ROTATE(T, z.p.p) ▹ Case 3
case2转化到case3,一次搞定修复性质。
0 0
- 红黑树的理解说明(插入)
- 理解红黑树的节点插入和删除
- 插入排序的理解
- 红黑树的理解说明(删除)
- 红黑树理解-插入删除
- 插入排序的通俗理解
- 对插入排序的理解
- C++前置说明的理解
- chmod的使用理解说明
- Python list 增加/插入元素的说明
- AVL树及关于插入的说明
- 我对插入排序算法的理解。
- 双向链表插入结点的理解。
- 数组插入算法的分析与理解
- 红黑树(RBTree)的插入算法以及如何测试一棵树是否是红黑树?(详细图解说明)
- 关于RTSP的理解和例子说明
- 关于RTSP的理解和例子说明
- 关于RTSP的理解和例子说明
- APK包名修改 请问如何修改APK包名
- gdb结合coredump定位崩溃进程
- 游戏开发一般分为哪几类?
- 使用jxl工具包创建修改excel文件
- Aizu 0005 GCD and LCM
- 红黑树的理解说明(插入)
- Java Ldap验证
- Android中Context详解 ---- 你所不知道的Context
- SDK Manager更新慢解决办法
- Windows下pip的安装
- lua安装流程完整流程
- magic_quotes_gpc
- Core Animation - 6
- centos彻底删除mysql