推荐看书:java数据结构和算法
考虑到有些童鞋看”java数据结构与算法”时,难以理解红黑树这一节,我对这一节的核心"插入一个新节点"章节,进行大白话的解释和思路流程的再梳理。
为了使得插入节点后的树是红黑二叉树,要怎么变色旋转插入?可以归纳为三种情况,并且这三种情况要按序执行:
1 在下行途中的颜色变换:
即遇到两个子节点为红色的父节点时,执行变色,如图1-1中 13 18 和19。
执行时间点:插入节点前执行
下图插入节点9(即0009)时的规则流程:
---------------------图1-1---------------------------
解释:如图1-1中,其中50为根节点,当想插入9(0009)时,9<50,向左走,再比较,9<25再向左走;在比较,9<18,再向左走,
往下遇到 "两个子节点为红色(13和19)" 的"黑色父节点"。
变色过程:13和19变黑色,18变红色
执行结果图:
2 在向下路途上的旋转
执行时间点:插入节点前
解释:为什么旋转,因为在执行 "1在下行途中的颜色变换" 颜色变换后,可能会遇到红红冲突的情况,18和25都是红色,这时需要旋转来解决颜色冲突的问题。
旋转次数,又因为节点是 ’ 祖父节点的内侧子节点还是外侧子节点 ’ 而不同。
假设我们称18为X,25为P,50为G(祖父)。
这里有个命名规则要注意,为什么我们把18命名为X,到底符合什么条件的节点我们把他命名为X呢?X是一个特殊节点,一般是违反规则的节点。
例如情况一我们把新插入的节点命名为x;
情况二 我们把父节点和子节点发生“红红”颜色冲突时的子节点成为X,就像这里执行“1 在下行途中的颜色变换”后,18和25出现红红颜色冲突,子节点18命名为X。
旋转过程:
这个属于祖父节点的外侧子节点(其他情况见书),先25 50变色,然后以G(50)为顶点旋转,同时要把以27为根节点的整颗子树横移,成为50的左子节点。
执行结果图:
-----------------图2--------------------------
3 插入节点后的旋转
执行时间点:插入节点后
假如我们想在2图的基础上,9下面再插入5。要想符合红黑树规则,9和13需要变色(具体如何变色旋转见书),13变色后会和18“红红”颜色冲突,这时需要根据“2 在向下途中的旋转”进行操作吗?答案是否定的,注意“执行时间点”,2是在插入前执行,我们现在是在插入后,所以要按照3的变色旋转情况执行。9和13先变色,然后以13为顶点,右旋转即可。
--------------图3--------------------
4 附
问:禅师,“1在下行途中的颜色变换” 和 “3插入节点后的旋转” 有淡淡的联系吗?
答:如果图2中13再有个红右子节点(15),那么就符合“1 在下行途中的颜色变换” 情况,我们只要直接用 1 方式处理即可。
问:禅师,图3的执行结果问题,假如我们想在2图的基础上,9下面再插入5,在查找插入点位置的过程中,会发现18和50为红,25为黑,按“1 在下行途中的颜色变换”的理论我们应该颜色变换,为什么你图3的结果图中18和50没改变颜色,你是不是想告诉我们要有一双发现问题的眼睛?
答:大意了,被你发现了。首先按照我上面讲的三种情况是绝对可以得到一棵正确的红黑数的,例如18和50红色是正确的,都变成黑色也是红黑树。其实按照我上文的步骤是先颜色变换,18和50变黑后,再接着执行"在9下面插入5”的操作。
但是为何图中的结果不是按照我上文的步骤呢?这是因为对于同一题,不同的人有不同的解决办法,有的书上介绍的是先变色再旋转,有的是先旋转然后把x赋值给祖父节点再判断有没有冲突。我自己懒得画图,就用网站上自动生成的图。
5 下篇 红黑树之java代码实现 http://blog.csdn.net/wabiaozia/article/details/78974861
我博客所有文章目录:http://blog.csdn.net/wabiaozia
转载请表明链接:http://blog.csdn.net/wabiaozia/article/details/53216228