前言

红黑树是数据结构中比较复杂的一种,最近与它交集颇多,于是花了一周的空闲时间跟它死磕,终于弄明白并实现了红黑树。写文总结一下,希望能给试图理解红黑树的同学一些灵感,也让我能记得更深刻。

在研究红黑树时吃了不少苦头,原因有二:

  • 红黑树的插入和删除非常复杂,很多人并没有理解或完全实现,或实现了的没有任何注释,让人很难参考;

  • 网络上红黑树的理解方式较为单一,一般是 双黑、caseN 法,而插入和删除的情况很多,每种都有对应的处理方式,如果死记硬背的话,再过一段时间再回忆各种情况可能就一头雾水了。

网络上讲红黑树的实现多来源于《算法导论》一书,直接讲红黑树的实现,需要处理颜色和高度两种属性约束,比较晦涩。本文通过红黑树的等同—— 2-3-4树,避开颜色属性约束,也弱化了高度的影响,以另一种方式去理解红黑树,虽然并不能完全降低它的复杂度,但自认为较之普遍实现,更易记一些。

文章最前面先放上红黑树的实现源码,代码在 Github 上,一开始实现时使用我最熟练的 PHP,后续添加了 Java 版,代码都可以直接运行。源码链接:GitHub-枕边书-RBTree,欢迎star


红黑树

定义

红黑树是一种结点带有颜色属性的二叉查找树,但它在二叉查找树之外,还有以下要求:

  1. 节点是红色或黑色。

  2. 根是黑色。

  3. 所有叶子都是黑色(叶子是NIL节点)。

  4. 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)

  5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

下图就是一个典型的红黑树:

但实现上我省略了其中的 Nil 结点,一般如下图,大家理解时也可以忽略它们。

优势和用途

我们知道二叉查找树在不停地添加或删除结点后,可能会导致结点情况如下:

这种情况下,二叉查找树的查找效率最坏会降低为 O(n)

而红黑树由于在插入和删除结点时都会进行变色旋转等操作,在符合红黑树条件的情况下,即使一边子树全是黑色结点,另一边子树全是红黑相间,两子树的高度差也不会超过一半。一棵有 n 个结点的红黑树高度至多为 2log(n+1),查找效率最坏为 O(log(n))

所以红黑树常被用于需求查找效率稳定的场景,如 Linux 中内核使用它管理内存区域对象、Java8 中 HashMap 的实现等,所以了解红黑树也很有意义。

下面介绍一下红黑树的等同 2-3-4树。


2-3-4树

定义

2-3-4树是四阶的 B树(Balance Tree),它的结构有以下限制:

  • 所有叶子节点都拥有相同的深度。

  • 节点只能是 2-节点、3-节点、4-节点之一。

    • 2-节点:包含 1 个元素的节点,有 2 个子节点;

    • 3-节点:包含 2 个元素的节点,有 3 个子节点;

    • 4-节点:包含 3 个元素的节点,有 4 个子节点;

  • 元素始终保持排序顺序,整体上保持二叉查找树的性质,即父结点大于左子结点,小于右子结点;而且结点有多个元素时,每个元素必须大于它左边的和它的左子树中元素。

下图是一个典型的 2-3-4树(来自维基百科):

2-3-4树的查询操作像普通的二叉搜索树一样,非常简单,但由于其结点元素数不确定,在一些编程语言中实现起来并不方便,实现一般使用它的等同——红黑树。

对应红黑树

至于为什么说红黑树是 2-3-4树的一种等同呢,这是因为 2-3-4树的每一个结点都对应红黑树的一种结构,所以每一棵 2-3-4树也都对应一棵红黑树,下图是 2-3-4树不同结点与红黑树子树的对应。

而上文中的 2-3-4树也可以转换成一棵红黑树:

由红黑树的性质5,和 2-3-4树的性质1,为了便于理解红黑树和 2-3-4树的对应关系,我们可以把红黑树从根结点到叶子结点的黑色结点个数定义为高度

红黑树和 2-3-4树的结点添加和删除都有一个基本规则:避免子树高度变化,因为无论是 2-3-4树还是红黑树,一旦子树高度有变动,势必会影响其他子树进行调整,所以我们在插入和删除结点时尽量通过子树内部调整来达到平衡,2-3-4树实现平衡是通过结点的旋转和结点元素数变化,红黑树是通过结点旋转和变色。

下面来对照着 2-3-4树说一下红黑树结点的添加和删除:


结点插入

2-3-4树中结点添加需要遵守以下规则:

  • 插入都是向最下面一层插入;

  • 升元:将插入结点由 2-结点升级成 3-结点,或由 3-结点升级成 4-结点;

  • 向 4-结点插入元素后,需要将中间元素提到父结点升元,原结点变成两个 2-结点,再把元素插入 2-结点中,如果父结点也是 4-结点,则递归向上层升元,至到根结点后将树高加1;

而将这些规则对应到红黑树里,就是:

  • 新插入的结点颜色为红色,这样才可能不会对红黑树的高度产生影响。

  • 2-结点对应红黑树中的单个黑色结点,插入时直接成功(对应 2-结点升元)。

  • 3-结点对应红黑树中的黑+红子树,插入后将其修复成 红+黑+红 子树(对应 3-结点升元);

  • 4-结点对应红黑树中的红+黑+红子树,插入后将其修复成红色祖父+黑色父叔+红色孩子子树,然后再把祖父结点当成新插入的红色结点递归向上层修复,直至修复成功或遇到 root 结点;

如上图所示,虽然向红黑树中插入了一个新结点,但由于旋转和变色,子树的高度保持不变。


删除结点

红黑树的删除要比插入要复杂一些,我们还是类比 2-3-4树来讲:

  • 查找最近的叶子结点中的元素替代被删除元素,删除替代元素后,从替代元素所处叶子结点开始处理;

  • 降元:4-结点变 3-结点,3-结点变 2-结点;

  • 2-结点中只有一个元素,所以借兄弟结点中的元素来补充删除后的造成的空结点;

  • 当兄弟结点中也没有多个元素可以补充时,尝试将父结点降元,失败时向上递归,至到子树降元成功或到 root 结点树高减1;

将这些规则对应到红黑树中即:

  • 查找离当前结点最近的叶子结点作为替代结点(左子树的最右结点或右子树的最左结点都能保证替换后保证二叉查找树的结点的排序性质,叶子结点的替代结点是自身)替换掉被删除结点,从替代的叶子结点向上递归修复;

  • 替代结点颜色为红色(对应 2-3-4树中 4-结点或 3-结点)时删除子结点直接成功;

  • 替代结点为黑色(对应 2-3-4树中 2-结点)时,意味着替代结点所在的子树会降一层,需要依次检验以下三项,以恢复子树高度:

    • 兄弟结点的子结点中有红色结点(兄弟结点对应 3-结点或 4-结点)能够“借用”,旋转过来后修正颜色;

    • 父结点是红色结点(父结点对应 3-结点或 4-结点,可以降元)时,将父结点变黑色,自身和兄弟结点变红色后删除;

    • 父结点和兄弟结点都是黑色时,将子树降一层后把父结点当作替代结点递归向上处理。

如上图,删除的要点是 找到替代结点,如果替代结点是黑色,递归向上依次判断侄子结点、父结点是否可以补充被删除的黑色,整体思想就是将删除一个黑色结点造成的影响局限在子树内处理。


小结

当然实现过程中调试也占了很大一部分,我使用了两项方法帮助调试:

  • 由于插入多个结点时,无法确定是处理哪个结点时出了问题,于是我给红黑树类添加了 debug 属性,用二分法设置此属性来找到问题结点;

  • 给红黑树类添加了 printTree() 方法,实时打印树结构,确定代码问题再分析;

由于红黑树相对其他树实在较为复杂,只通过思考就完全理解不太现实,还需要自己去试着画,试着实现,我画了 5 张 A4 纸的正反面才算理解了红黑树,即便如此,在写这篇文章时还发现了代码中的可优化点。

而且代码实现比画图还略复杂,理论中的一个旋转就包含了 左旋/右旋/先左旋再右旋/先右旋再左旋 几种情况,虽然有一定规律,还是自己实现一下印象最深刻。

END

版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。

如果你觉得文章不错,文末的赞 ???? 又回来啦,记得给我「点赞」和「在看」哦~

通过2-3-4树理解红黑树相关推荐

  1. 从2-3树理解红黑树

    说起红黑树就头痛,在大学时就没搞懂,看的晕晕乎乎,理解不了.直到前几天在极客时间的<数据结构与算法之美>专栏中的<26 | 红黑树(下):掌握这些技巧,你也可以实现一个红黑树 > ...

  2. 关于2-3-4树和红黑树的简单理解

    在介绍红黑树之前需要我们了解一下什么是2-3-4树 一.2-3-4树简介 2-3-4树属于一种多路查找树,树是从下往上生成的,具有以下的特点 1.所有的叶子节点都拥有相同的深度 2.节点只能2-节点. ...

  3. 【数据结构】利用4阶B树辅助理解——红黑树删除节点

    文章目录 学习目标: 学习内容: 一.删除节点的过程 二. 删除对象的转换 三.失黑的原因&失黑修正原则 3.1失黑的原因 3.2 失黑修正原则 3.2.1 可以在节点内部平衡的情况 3.2. ...

  4. 红黑树的删除_从红黑树的本质出发,彻底理解红黑树!

    前言 早上好,我是彤哥. 上一节,我们一起从二叉树.二叉查找树.平衡树.AVL树.2-3树.2-3-4树.B树,一路讲到红黑树,最后得出红黑树的本质:红黑树就是2-3-4树,请看下图: 我们知道2-3 ...

  5. 从2-3树到 红黑树

    原文:   查找(一)史上最简单清晰的红黑树讲解 二叉查找树由于可能会非常的不均衡. 所以用2-3树. 采用上上浮的方法,顶多多两倍节点数. 红黑树一直是数据结构中的难点,大部分关于算法与数据结构的学 ...

  6. 清晰理解红黑树的演变---红黑的含义

    前言 红黑树,对不少人来说是个比较头疼的名字,在网上搜资料也很少有讲清楚其演变来源的,多数一上来就给你来五条定义,红啊黑啊与根节点距离相等之类的,然后就开始进行旋转.插入.删除这些操作.一通操作下来, ...

  7. 我画了近百张图来理解红黑树

    文章已同步发表于微信公众号JasonGaoH,我画了近百张图来理解红黑树,文章略有修改. 之前在公司组内分享了红黑树的工作原理,今天把它整理下发出来,希望能对大家有所帮助,对自己也算是一个知识点的总结 ...

  8. 【算法】958- 动图演示:彻底理解红黑树?

    本文主要讲解下最近一直听到的红黑树,看看究竟是什么神 二叉树 满足以下两个条件的树就是二叉树: 本身是有序树(若将树中每个结点的各子树看成是从左到右有次序的(即不能互换),则称该树为有序树(Order ...

  9. 动图演示:彻底理解红黑树?

    本文主要讲解下最近一直听到的红黑树,看看究竟是什么神 二叉树 满足以下两个条件的树就是二叉树: 本身是有序树(若将树中每个结点的各子树看成是从左到右有次序的(即不能互换),则称该树为有序树(Order ...

最新文章

  1. java后台开发加密程序_Java后端实现MD5加密的方法
  2. 设计模式 适配器模式
  3. Mysql梳理(多表查询)
  4. vs2010 mysql linq to sql 系列_linq to sql简单使用
  5. 将文件标记为 side-effect-free(无副作用)
  6. Vue-cli搭建vue基础项目
  7. you don't have permission to access forbidden
  8. 相亲交友小程序的盈利点
  9. java 多语言_JAVA实现多语言
  10. android studio mipmap下创建不同分辨率的文件夹
  11. pytorch nn.AdaptiveAvgPool2d(1)
  12. 调侃计算机专业的笑话,段子手要失业了 计算机也懂幽默
  13. linux 韦恩图两个,在线&在R中绘制韦恩图的几种方法 和 一些漂亮的venn图
  14. 第十一届中国云计算标准和应用大会 | 华云数据成为全国信标委云计算标准工作组云迁移专题组副组长单位副组长单位
  15. 仿抖音写上下滑动切换视频
  16. Git入门、gitHub、gitee、gitLab远程库的学习和集成IDEA
  17. 大整数的加减乘除运算
  18. MySQL之中间件Mycat实现读写分离
  19. Cloudflare免费CDN加速及防护
  20. 单片机-硬件接口(UART/IIC/SPI/RS232/USB/CAN)异同

热门文章

  1. 【汇正财经】什么是股票交割方式?股票交割方式有哪些?
  2. 用CNN做在NLP句子分类
  3. python金融数据分析单元测试答案_参考答案2020智慧树知到Python金融数据分析
  4. 调取python背景减法库:MOG2和KNN,非常好用
  5. Linux网络-网络配置命令
  6. 【方法】科大讯飞在线语音合成API使用-文字转语音音频
  7. 【MATLAB航空航天工具箱】学习笔记--时间系统
  8. Xdelta3 bsdiff Courgette三种差分算法比较
  9. 登陆mysql的命令行
  10. C语言编程>第三周 ④ 求100之内的素数。