前言
本篇博客我们说一说如何从无到有创建一颗红黑树,并在创建红黑树的过程中理解其构造原理。
红黑树规则
首先我们复习一下红黑树的五项规则,如下:
- 规则一:每个节点或者是黑色,或者是红色;
- 规则二:根节点是黑色;
- 规则三:每个叶子节点(NIL/NULL)是黑色;
- 规则四:如果一个节点是红色的,则它的子节点必须是黑色的;
- 规则五:从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点;
插入规则
其次我们知道要将一个节点N插入到红黑树的时候是要根据二叉查找树的规则进行的,即比某节点X小往其左子树走,比某节点X大则往其右子树走,一直比较下去直至叶子节点;
待插入节点的颜色
然后我们需要对待插入的节点进行着色,那么着什么色呢?答案是红色,可是为什么呢?黑色不行吗?
结合上面说过的红黑树的五项规则我们知道,如果把待插入的节点着色为黑色,那么插入新节点后的红黑树一定是违背规则五的,所以每次插入新节点后都需要进行修正;
而如果把待插入的节点着色为红色,插入后的红黑树肯定是不会违背规则五,但是可能会违背规则二或者规则四(每次插入最多只可能会违背其中一项),所以每次插入后红黑树可能会需要修正,也有可能不需要修正,这就意味着我们需要处理的情况会比着色为黑色的情况要少!
修正规则
什么情况下需要对插入新节点后的红黑树进行修正?
我们需要结合红黑树的五项规则和待插入节点的颜色为红色这两点来看!
当新插入一个节点时,首先规则一和规则三不用管,又因为待插入节点的颜色为红色的,所以规则五也不用管(但是在修正过程中可能会违背规则五);
而对于规则二,只有在插入第一个节点或者修正过程中会违背(插入第一个节点时肯定违背,因为待插入节点的颜色为红色),但是处理策略也很简单,直接将新插入的节点/当前节点重新着色为黑色即可;
如果新插入节点的父节点是黑色,那么不用管,插入后的红黑树还是符合规则的,如果新插入节点的父节点是红色,那么就需要进行修正了,因为违背了规则四,具体处理策略如下:
违背规则四时 | 现象说明 | 处理策略 |
---|---|---|
情况一 | 当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色 | (01) 将父节点设为黑色; (02) 将叔叔节点设为黑色; (03) 将祖父节点设为红色; (04) 将祖父节点设为当前节点(红色节点); (05)之后继续对当前节点进行判断是否违背规则并操作; |
情况二 | 当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子 | (01) 将父节点设为黑色; (02) 将祖父节点设为红色; (03) 以祖父节点为支点进行左旋; |
情况三 | 当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子 | (01) 将父节点作为新的当前节点; (02) 以新的当前节点为支点进行右旋; (03)之后继续对新的当前节点进行判断是否违背规则并操作; |
插入演示
- 1、插入节点100
由于红黑树为空,节点100直接作为根节点,但是违背规则二,下面进行修正,直接将新插入的节点重新着色为黑色即可;
- 2、插入节点200
插入后符合红黑树规则,无需修正;
- 3、插入节点150
违背规则四,且符合情况三,下面进行修正;
现在的当前节点是200,并且还是违背了规则四,不过符合情况二,继续进行修正;
二次修正后符合红黑树规则,无需继续修正!
- 4、插入节点300
此时违背规则四,符合情况一,下面进行修正;
此时违背规则二,直接将新插入的节点/当前节点重新着色为黑色即可;
- 5、插入节点400
此时违背规则四,且符合情况二,下面进行修正;
修正后符合红黑树规则,无需继续修正!
总结
红黑树的插入步骤及基本情况如上所示,大家也可以使用这个http://sandbox.runjs.cn/show/2nngvn8w网页进行在线模拟,理解更加深刻!
参考
http://www.cnblogs.com/skywang12345/p/3245399.html