内容简介:在研究集合类源码的时候,发现Map,Set里面不少用到红黑树,为了能够更顺利的学习源码。我决定把红黑树知识恶补一下。我强烈建议大家的阅读顺序为:先读OK,现在就当大家已经按上面步骤阅读完了。如果此时还有疑问或不懂的地方,可以继续往下阅读,也可以在评论中询问我,我会尽力回答。由于个人只是对红黑树的删除部分觉得有难点,所以下面主要讲的是红黑树删除部分。
在研究集合类源码的时候,发现Map,Set里面不少用到红黑树,为了能够更顺利的学习源码。我决定把红黑树知识恶补一下。 如果不了解树、二叉树、平衡二叉树定义的同学先了解一下这些前提知识。 由于能力时间有限,我就不复述学习资料里大神写的内容了。关于一些基础知识和概念请大家先读一遍学习资料里的文章。我接下来的讲解都将基于这三篇的基础之上,进行更细致的讲解,把我在学习过程中遇到的一些比较难理解的点尝试用文字或图例变得更容易理解。
我强烈建议大家的阅读顺序为:先读 红黑树详细分析,看了都说好 。这篇文章讲的比较全,但是删除部分对我来说,文字上有点难理解。接着阅读红黑树删除操作。这篇文章把删除讲解的比较细致。最后再阅读 红黑树从头至尾插入和删除结点的全程演示图 或码图并茂红黑树。前者格式不好,后者漏了一步,可以主要以后者为主。两篇文章就是来学以致用的,文章以图来全程演示此红黑树的所有插入,和删除情况。但是缺点是没有任何讲解,所以正适合检验一下前两篇的学习和理解,建议大家可以先自己推理一步,然后再看与文章中的下一步的结果图是否一致。
OK,现在就当大家已经按上面步骤阅读完了。如果此时还有疑问或不懂的地方,可以继续往下阅读,也可以在评论中询问我,我会尽力回答。由于个人只是对红黑树的删除部分觉得有难点,所以下面主要讲的是红黑树删除部分。
红黑树删除
前提知识
1. 红黑树的定义
- 任何一个节点非红即黑;
- 树的根为黑色;
- 叶子节点为黑色(注意:红黑树的所有叶子节点都指的是Nil节点);
- 任何两个父子节点不可能同时为红色;
- 任何节点到其所有分枝叶子的简单路径上的黑节点个数相同;
2. 节点命名约定
D表示要被删除的节点。即:取 Delete 的首字母;
P 表示父节点。即:取 Parent 的首字母;
S表示兄弟姐妹节点。即:取 Sibling的首字母;
U表示叔伯节点。即:取Uncle的首字母;
G表示祖父节点。即:取 Grandfather的首字母;
L表示左树。即:取Left的首字母 ;
R表示右树。即:取Right的首字母;
Nil表示叶子节点。即所谓的空节点;注意:红黑树中的叶子节点与其他树中所述说的叶子节点不是同一概念。而且红黑树中的叶子节点(即:Nil节点)永远是被定义为黑色的。
下文的节点命名表示将会使用以上这些命名约定或它们的组合表示。因此,请先牢记这些命名约定。举例:
DR表示要被删除的节点的右子树,即:右子节点; SL表示兄弟节点的左子树,即:左子节点;
3. 删除操作宏观分析
在红黑树中,删除一个节点往大的说,只有以下四种情况。
情况一:删除的节点的左、右子树都非空;
情况二:删除的节点的左子树为空树,右子树非空;
情况三:删除的节点的右子树为空树,左子树非空;
情况四:删除的节点的左、右子树都为空树;
其中情况一,可以按与其他二叉搜索树的删除方式一样处理,最终可以转换到后面的三种情况。 具体为:找到(Old)D节点的直接 后继节点(暂且称为X节点)
,然后将X的值转移到D节点,最后将X节点作为真正要被删除掉的节点(即:(Real)D节点)。 这样删除操作后,可以保证该树仍然为一棵二叉搜索树。但由于红黑树的定义(即:红黑树的性质)约定。这样删除(Real)D节点后,可能会破坏红黑树的性质。所以需要额外做一些调整处理,这便是下面将要详细讨论的内容。 说明:下文中所提到的D,除非有特别说明,否则都将指的是(Real)D。
删除情况分类
通过阅读 红黑树详细分析,看了都说好 、红黑树删除操作 两篇文章,可以发现虽然说法不同,但是绝大多数应对的情形是一样,我整理为下列表格:
图例 | 《红黑树删除操作》 | 《红黑树详细分析》 | 备注 |
---|---|---|---|
被删除D为红 | 只需要直接将D节点删除,并将DR作为P的左子节点即可。 | ||
D为黑,DR不为Nil、DR必为红 | 由于红黑树定义5,(P-D-Nil)和(P-D-DR-Nil)的黑点数一样,所以DR必为红 | ||
D黑、DR为Nil、S红 | 情况二 | 仍需继续平衡 | |
D黑、S黑、SL红 | 情况五(后续为情况六) | 这里两篇文章有些不同,《删除操作》中单独处理,《详细分析》将与情况六搭配起来处理平衡,但是结果是一样的。个人喜欢使用情况五六搭配起来使用方式 | |
D黑、S黑、SR红 | 情况六 | ||
D黑、S黑、P红、SL黑、SR黑 | 情况四 | ||
D黑、S黑、P黑、SL黑、SR黑 | 情况三 | 可能仍需继续平衡,此时经过P的路径的黑节点个数将会比不经过它的路径少一个。因此,我们将P作为待平衡的节点(即:此时的P相当于DR的角色)往上继续上溯,直到P为根节点为止。 |
D黑、DR为Nil、S红(情况二)详解
在 红黑树删除操作 中 D黑、DR为Nil、S红
这个分支个人认为讲的有点太绕了。图画的容易让人混淆。我重新画个图方便大家理解。其实作者省略了SL和SR的叶子节点,准确的红黑树图应该如下:
此时,当通过旋转变色之后,得到的结果如下:
可以发现,此时乍看一下好像是平衡了,但是把叶子结点加上后,就会发现(S-P-DR)这条线比其他线少一个黑结点。此时需要继续平衡,这个时候我们的DR结点的兄弟结点是SL,所以匹配D黑、S黑、P红、SL黑、SR黑
的情况。
所以最终平衡结果如下:
在删除结点演示图中的删除结点16,就是这个情况。
红黑树删除结点演示图部分详解
这里我们根据 红黑树从头至尾插入和删除结点的全程演示图 的删除演示图,详解其中的几步。
删除结点12
先寻找到结点12的后继结点13,然后将13的值复制到结点12处,将结点13删除,此时可以发现匹配 D黑、S黑、SR红
的情况(因为是镜像的原因,所以是SR红不是SL红),根据匹配的结果旋转变色,最后得到结果红黑树:
删除结点13
此时红黑树为,我们将删除结点13
把注意力集中在13-16-17这棵红黑树上,发现匹配D黑、S黑、P黑、SL黑、SR黑
情形,根据匹配结果着色为下图(右):
此时以结点16为根的红黑树平衡了,但是我们把目光放在整棵红黑树上,会发现所有经过结点16的黑节点数会比不经过结点16的少1,所以根据D黑、S黑、P黑、SL黑、SR黑
的备注,我们将原P(结点16)作为待平衡的节点(DR)往上继续上溯,直到P为根节点为止。如下图所示(结点16连线断开仅是为了防止匹配时被红结点17干扰):
最后
最后,如果你也在学习红黑树,希望这篇文章能够帮助到你。另外,由于红黑树本身比较复杂,加之本人水平有限,难免会出一些错误。如果有错或者有疑问,还望大家指出来,我们共同讨论。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于行列式点过程的推荐多样性提升算法
- AI透明度引发关注 科技巨头推工具解释算法决策过程
- 存储过程 – 重新编译后,存储过程运行得很快
- 面试:谈谈你对 MyBatis 执行过程之 SQL 执行过程理解
- 死磕Android_App 启动过程(含 Activity 启动过程)
- 【PHP源码学习】关于$a=1整个过程的gdb过程与相关验证
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
实战Linux编程精髓
罗宾斯 / 中国电力出版社 / 2005-7 / 59.80元
编写应用软件,特别是那些比较重要的软件,毫无疑问要涉及到系统调用。在UNIX/Linux环境下编程更是如此。要想编写优秀的软件,就必须熟悉这些系统调用的方方面面。通过阅读这本书,你能够快速地掌握这些重要技术,以构建严谨的Linux软件。全书主要分为三大部分:第一部分讨论了基本的编程问题,包括Linux编程环境、基本的文件和进程管理与操作、内存操作,还介绍了一些基本的库接口。第二部分比较深入地讨论了......一起来看看 《实战Linux编程精髓》 这本书的介绍吧!