哈喽,大家好,我是二叉排序树,外号二叉查找树兼二叉搜索树,你可以叫我二哈,呸,二叉。
我知道你们是来看红黑树的,但是请有点耐心,有我的帮助,你们能看得更清楚,更透彻。
喏,就是她咯,先有个印象。
二叉排序树
简单介绍一下我自己,放一张自拍照最合适。
看到了吧,我的特点:每一个节点的值都大于左子节点,并且小于右子节点。
这一章主要介绍红黑树的删除。所以先从我自己的删除开始。
你问为啥没有新增?还说没有新增何来删除?
好吧,贴一篇新增的文章。《20+秘制图片,带你看懂红黑树》
我的删除主要有三种情况。
- 删除叶子节点。
- 删除的节点只有一个子节点。
- 删除的节点有左右子节点。
第一种情况,直接删除就好。
第二种情况,让父节点指向删除节点的子节点,然后删除该节点即可。
第三种情况,稍微复杂一点,但是相信我,也仅仅只是复杂一丁点儿。
首先找到删除节点的后继节点,然后交换后继节点和要删除节点的值,删除后继节点的值即可。
所谓后继节点,就是比当前节点大,且最近的哪一个。
后继节点
为了你更好的理解后继节点,我举个栗子。将下图中的数值取出来排序,结果如下:
10 < 20 < 30 < 40 < … … 可以轻松看出,20的后继节点就是30。
来看我的亲身示范。
事实上,找到前继节点通过替换删除也行。聪明的你,肯定立刻就能明白通过前继节点怎么删除,想一想呢?
好了,介绍完我的删除,接下来就是红黑树了。
红黑树删除麻烦的地方,在于删除后不能破坏她的五条规则,不满足规则,就不能称之为红黑树了。
在这里我带你们回顾一下红黑树的约法五章(五条规则)。
- 1.节点是红色或者黑色
- 2.根节点是黑色
- 3.每个叶子节点是黑色的(NIL节点也叫空节点)
- 4.不存在两个连续的红色节点(黑色节点可以连续)
- 5.从根节点出发,到任意一个叶子节点(NIL),都包含相同数量的黑色节点
前面四条都非常容易理解,可能不容易理解的就是第五点了。着重给大家讲一下。
如图,我用四种不同颜色的线条,画出了从根节点出发,到叶子节点的所有路径(此时暂时忽略NIL,也就是忽略空节点)。第一条线路上(橙色),经过的黑色节点有两个,40和10;
第二条线路(绿色),经过的黑色节点有两个,40和30;
第三条线路上(黄色),经过的黑色节点有两个,40和60;
第四条线路上(紫色),经过的黑色节点有两个,40和60。
发现没有,从根节点出发,到每个叶子节点上,每条路径上黑色节点的数量都是相同的。规则五:根节点到叶子节点的每一条线路上,黑色节点的数量都是相同的。明白了没?
关于删除过程,我本着先易后难的原则给大家介绍,同新增的情况一样,删除主要也是靠两大必杀技保持平衡:乾坤大挪移和七十二变,通俗说法就是旋转和变色。
变色理解起来很简单,要么把红色节点变成黑色,要么就是把黑色节点变成红色。
至于乾坤大挪移(旋转),那可是和红黑树深入了解的关键,要是学不会,你就别想着明白红黑树了,建议可以反复多看几遍。
静下心来,学会旋转,红黑树你就懂了大半。
左旋:先放一张动图,帮助理解。
接下来举一个栗子(请忽略颜色,只注意旋转过程)
右旋:还是先放一张动图,帮助理解。
接下来举一个栗子(请忽略颜色,只注意旋转过程)
接下来,我把红黑树删除的各种情况罗列出来,相信聪明的你,肯定一学就会。
- 删除红色节点
1.1 红色为叶子节点。
直接删除即可。
1.2 红色为非叶子节点
此时只会存在有两个子节点的情况,否则违背红黑树的约法五章。
处理方法有两种:
方法一、找到后继节点,将后继节点的值与删除节点交换,然后删除后继节点即可。
方法二、也可以找到前继节点,将前继节点的值与删除节点交换,然后删除前继节点。给大家推荐的工具网站(见文末),就是使用删除前继节点的方式。
两种方式效果相同,此处给出方法一图解:
- 删除黑色节点
2.1删除黑色非叶子节点
2.1.1 删除的黑色节点存在两个子节点
首先找到被删除节点的后继节点,然后用后继节点的值,替换删除节点的值,此时转换为删除后继节点。作为后继节点,是绝对不可能拥有两个子节点的(理解起来有点绕,单独解释),所以情况转换为2.1.2。
先解释:为什么后继节点(文中提到的后继节点,均指直接后继节点)绝不可能拥有两个子节点?看图说话
通过上图三个栗子,我希望大家发现,后继节点只可能拥有一个子节点,或者没有子节点。比如最开始40的后继节点是60,但60在拥有两个子节点后,40的后继节点变为50。即,拥有两个子节点的节点,不可能作为任何节点的后继节点
删除有两个子节点的黑色节点,看图:
2.1.2 删除节点存在一个子节点
用子节点替换删除节点,然后修改子节点为黑色即可。
2.2 删除黑色的叶子节点(最后一个大分类了,再坚持一下。)
这种情况可细分为七类,处理方式并不见得比上面的复杂,但就是可能出现的情况太多。
A: 删除节点的兄弟节点是红色
A-1 删除节点是左节点
将父节点和兄弟节点颜色互换,再执行左旋操作。此时兄弟节点变成了黑色,也就是B、C分类要讨论的情况。
A-2 删除节点是右节点
依然将父节点和兄弟节点颜色互换,不过这次执行右旋操作,将其转换为兄弟节点为黑色的情况处理。
B:兄弟节点为黑色,远侄子节点为红色
B-1:删除节点是左子节点
将父节点和兄弟节点颜色互换,然后对父节点执行左旋操作,最后把远侄子节点变黑,并删除节点。
B-2:删除节点是右子节点
将父节点和兄弟节点颜色互换,然后对父节点执行右旋操作,最后把远侄子节点变黑,并删除节点。
C:兄弟节点为黑色,远侄子节点为黑色,近侄子节点为红色
C-1:删除节点是左节点
交换兄弟节点和近侄子的颜色,再对近侄子执行右旋操作,此时变成了B-1情况,参照B-1处理即可。
C-2:删除节点是右节点
交换兄弟节点和近侄子的颜色,再对近侄子执行左旋操作,此时变成了B-2的情况,参照B-2处理即可。
D:父节点为红色,兄弟节点是黑色,且兄弟节点的两个孩子是空节点。
将父节点变为黑色,兄弟节点变为红色,再删除节点即可。
E:父节点为黑色,兄弟节点为黑色,且兄弟节点的两个孩子是空节点。
将兄弟节点变红色,再删除节点。此时经过父节点的黑色节点-1,还需根据删除后的情况,继续调整。
好啦,到此介绍完毕,小二叉我也就撤了。
推荐工具网站,一边看文章,一边实际操作,更容易掌握。
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
嗯哼,大家好,我是正经人 – -- 月亮,我尝试着把技术文写得简单一些,毕竟做技术已经很不容易了,学技术还是用更轻松的方法好。写一篇技术文并不容易,希望能得到一些正反馈,更能坚持下去。比如帮我在文末点个赞。如有纰漏也欢迎指正,犯错事小,误人子弟事大。
任何美好的事情都值得分享,关于生活,关于工作。如果你喜欢我的文章,可以关注我的公众号【猿月亮】和我互动哦。