1.u存在且为红色
2.u不存在
3.u存在且为黑色
4.2.1情况1:变色
c为红,p为红,g为⿊,u存在且为红,则将p和u变⿊,g变红。在把g当做新的c,继续往上更新。
分析:因为p和u都是红⾊,g是⿊⾊,把p和u变⿊,左边⼦树路径各增加⼀个⿊⾊结点,g再变红,相当于保持g所在⼦树的⿊⾊结点的数量不变,同时解决了c和p连续红⾊结点的问题,需要继续往上更新是因为,g是红⾊,如果g的⽗亲还是红⾊,那么就还需要继续处理;如果g的⽗亲是⿊⾊,则处理结束 了;如果g就是整棵树的根,再把g变回⿊⾊。
情况1只变⾊,不旋转。所以⽆论c是p的左还是右,p是g的左还是右,都是上⾯的变⾊处理⽅式。
这就是第一种情况:u存在且为红的处理方式,下面我们来看这种情况的示意图:
在这种情况中我们是不需要旋转的,只需要变色即可。当然,这只是其中最简单的一种情况,所以我们一般看抽象图。
和上一篇AVL树一样,我们来看一看某些情况来理解为什么我们要看抽象图。
这是hb=0的情况。
这是hb=1的情况。
这是hb=2的情况。
这里可以看出,相比hb=1而言仅仅只多了一个hb,就多了非常多种情况,所以说我们要要看抽象图。
下面我们就实现下变色这种情况的代码:
在控制循环条件中我们不仅要判断此时parent是否为空,还要判断此时的parent是红色才能进入循环,如果parent是黑色就不需要更新颜色。
这里我们先写parent在grandfather的左边的情况,将三种情况写完,parent在右边直接复制过去,再改些值就可以。
里面的代码就是根据我们上面写的变色过程来完成,并且在完成一次变色后,要继续向上判断。
4.2.2情况2:单旋+变色
c为红,p为红,g为⿊,u不存在或者u存在且为⿊,u不存在,则c⼀定是新增结点,u存在且为⿊,则 c⼀定不是新增,c之前是⿊⾊的,是在c的⼦树中插⼊,符合情况1,变⾊将c从⿊⾊变成红⾊,更新上来的。
分析:p必须变⿊,才能解决,连续红⾊结点的问题,u不存在或者是⿊⾊的,这⾥单纯的变⾊⽆法解 决问题,需要旋转+变⾊。
如果p是g的左,c是p的左,那么以g为旋转点进⾏右单旋,再把p变⿊,g变红即可。p变成这颗树新的根,这样⼦树⿊⾊结点的数量不变,没有连续的红⾊结点了,且不需要往上更新,因为p的⽗亲是⿊⾊还是红⾊或者空都不违反规则。
如果p是g的右,c是p的右,那么以g为旋转点进⾏左单旋,再把p变⿊,g变红即可。p变成这颗树新的根,这样⼦树⿊⾊结点的数量不变,没有连续的红⾊结点了,且不需要往上更新,因为p的⽗亲是⿊⾊还是红⾊或者空都不违反规则。
根据上面的规则我们来写情况2的代码:
右单旋我们在AVL树那一章节已经讲过,这里就不过多赘述,红黑树中的右单旋与其不同的是不需要判断平衡因子的情况了。
剩下的就和AVL树中的一样,最后将parent和grandfather变色即可。
最后我们来看一下单旋+变色的过程。
4.2.3情况3:双旋+变色
c为红,p为红,g为⿊,u不存在或者u存在且为⿊,u不存在,则c⼀定是新增结点,u存在且为⿊,则 c⼀定不是新增,c之前是⿊⾊的,是在c的⼦树中插⼊,符合情况1,变⾊将c从⿊⾊变成红⾊,更新上来的。
分析:p必须变⿊,才能解决,连续红⾊结点的问题,u不存在或者是⿊⾊的,这⾥单纯的变⾊⽆法解决问题,需要旋转+变⾊。
如果p是g的左,c是p的右,那么先以p为旋转点进⾏左单旋,再以g为旋转点进⾏右单旋,再把c变
⿊,g变红即可。c变成这颗树新的根,这样⼦树⿊⾊结点的数量不变,没有连续的红⾊结点了,且不需要往上更新,因为c的⽗亲是⿊⾊还是红⾊或者空都不违反规则。
如果p是g的右,c是p的左,那么先以p为旋转点进⾏右单旋,再以g为旋转点进⾏左单旋,再把c变
⿊,g变红即可。c变成这颗树新的根,这样⼦树⿊⾊结点的数量不变,没有连续的红⾊结点了,且不需要往上更新,因为c的⽗亲是⿊⾊还是红⾊或者空都不违反规则。
我们根据上面的规则来写情况3的代码:
经过上面的单旋其实我们也可以看出,红黑树的单旋和双旋情况和AVL树是很类似的,无非就是需要旋转的条件不同,但是一旦要旋转,结点的分布是一样的。
旋转过后改变cur和grandfather的颜色即可。
最后我们看一下双旋+变色的过程。
下面就是parent在grandfather右边的代码:
这里要注意的是我们在旋转过后就要break来停止循环,否则会出问题的。
这里可能有人会有一个疑惑:那经过上述的操作后,如果根结点被改为红色呢?
我相信在讲上面的操作中,有人疑惑我为什么不判断根结点是否被改变,因为我们这里可以暴力解决:
我不管你中间经过了什么步骤,在循环结束时,我直接对根结点的_col进行修改,将其改为黑色,这样就完美解决上面的问题,并且简单又简洁。
5.红黑树的判断
我们在写完了红黑树,如何判断它是否是红黑树呢?
在AVL树的章节,我们是通过判断高度差来判断是否是AVL树,而在红黑树中显然我们不能这样判断。
那么能不能根据颜色来判断呢?
答案也不能,在红黑树中,我们要判断的话要根据红黑树的四条规则来判断,这样才严谨。
我们判断的思路是:先找出任意一条路径的黑色节点的个数,在遍历其他路径判断黑色节点的个数是否相同,并在遍历的途中判断有没有连续的红色结点,这样就能兼顾红黑树的四条规则。
在上面的代码中,我以最左边的路径为标准,来检查左右子树是否都为红黑树。
其中要注意的就是检查有无两个连续的红色结点时,要找其parent,原因上面我也写了,最后如果左右子树都是红黑树返回true,不满足就返回false。
最后我们来看一下递归过程的示意图。
还有一些像:Find,Inorder,Size和Height这些函数和AVL树那篇中的一样,这里就不写了。而红黑树的删除和AVL树的删除一样都不在讲解,理由也是一样的,对于两者而言,我们通过插入了解两者是如何控制平衡的即可,熟悉控制平衡的过程,都有哪些情况。
https://www.dongchedi.com/article/7600833157193253401
https://www.dongchedi.com/article/7600834099257016856
https://www.dongchedi.com/article/7600832447063999000
https://www.dongchedi.com/article/7600832867085713945
https://www.dongchedi.com/article/7600831262563598873
https://www.dongchedi.com/article/7600831402183311897
https://www.dongchedi.com/article/7600832061917905470
https://www.dongchedi.com/article/7600832733291594264
https://www.dongchedi.com/article/7600831880816132632
https://www.dongchedi.com/article/7600831372500140568
https://www.dongchedi.com/article/7600830983973110297
https://www.dongchedi.com/article/7600830989874577944
https://www.dongchedi.com/article/7600829992859484697
https://www.dongchedi.com/article/7600831200579633688
https://www.dongchedi.com/article/7600828893398254104
https://www.dongchedi.com/article/7600829947162739225
https://www.dongchedi.com/article/7600830440379204158
https://www.dongchedi.com/article/7600830705475813950
https://www.dongchedi.com/article/7600829156548837913
https://www.dongchedi.com/article/7600828482650194457
https://www.dongchedi.com/article/7600829257937584702
https://www.dongchedi.com/article/7600829728349684248
https://www.dongchedi.com/article/7600828048296083993
https://www.dongchedi.com/article/7600829419913511486
https://www.dongchedi.com/article/7600826526896112152
https://www.dongchedi.com/article/7600825958186648089
https://www.dongchedi.com/article/7600826072481055257
https://www.dongchedi.com/article/7600826004273431065
https://www.dongchedi.com/article/7600826285178536472
https://www.dongchedi.com/article/7600825958186418713
https://www.dongchedi.com/article/7600825908014252569
https://www.dongchedi.com/article/7600826379294704190
https://www.dongchedi.com/article/7600826004273267225
https://www.dongchedi.com/article/7600826379294573118
https://www.dongchedi.com/article/7600825908014154265
https://www.dongchedi.com/article/7600825816129765913
https://www.dongchedi.com/article/7600826257907466814
https://www.dongchedi.com/article/7600825708680135193
https://www.dongchedi.com/article/7600826257907270206
https://www.dongchedi.com/article/7600825908013924889
https://www.dongchedi.com/article/7600825653575303705
https://www.dongchedi.com/article/7600763089105469977
https://www.dongchedi.com/article/7600825816129471001
https://www.dongchedi.com/article/7600825816129339929
https://www.dongchedi.com/article/7600761478211224089
https://www.dongchedi.com/article/7600826159441904190
https://www.dongchedi.com/article/7600763029579743806
https://www.dongchedi.com/article/7600763312351101465
https://www.dongchedi.com/article/7600755747886334488
https://www.dongchedi.com/article/7600758147854549566
https://www.dongchedi.com/article/7600825603486876185
https://www.dongchedi.com/article/7600711725914014233
https://www.dongchedi.com/article/7600708729394217534
https://www.dongchedi.com/article/7600825816129569305