红黑树是怎么实现的,看这篇真的就够了!

article/2025/9/21 0:22:15

大家好,我是鸭血粉丝,又是一个元气满满的周一,今天带大家一文搞懂红黑树,友情提示:本文较长,建议先收藏再观看。

红黑树由来:在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees),后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的红黑树,就此红黑树出现在软件开发者的视野里!
 

一、摘要

在上篇文章中,我们详细的介绍到平衡二叉查找树的算法以及代码实践,我们知道平衡二叉查找树是一个高度平衡的二叉树,也就是说树的高度差不能大于1,在删除的时候,可能需要多次调整,也就是左旋转、右旋转操作,在树的深度很大的情况下,删除效率会非常低,如何提高这种效率?

红黑树由此诞生了,了解过红黑树的朋友们一定知道,红黑树是一个基本平衡的二叉树,英文全称:red-black-tree,简称:RBT,特性如下:

  • 1.每个节点要么是黑色要么是红色;
  • 2.根节点是黑色;
  • 3.每个叶子节点是黑色;(注意:这里叶子节点,是指为空的叶子节点)
  • 4.如果一个节点是红色的,则它的子节点必须是黑色的;(说明父子节点之间不能出现两个连续的红节点)
  • 5.从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点;

关于它的特性,需要注意的是:

  • 特性3中的叶子节点,是只为空(NIL 或 null)的节点;
  • 特性5,确保没有一条路径会比其他路径长出俩倍,因而,红黑树是相对的接近平衡的二叉树!(比如,包含相同数目为3的黑节点路线,最短路线:黑节点 -> 黑节点 -> 黑节点,长度为3;最长路线:黑节点 -> 红节点 -> 黑节点 -> 红节点 -> 黑节点,长度为5

红黑树示例图,如下:

图片

红黑树,与二叉树,在查询、插入、删除方面,都是一样的,最大的不同点是,插入、删除需要重新调整树的形态,以保持红黑树的特性!
 

二、算法思路

在上篇平衡二叉树的文章中,我们了解到为了保证树的高度差不超过1,我们通过树高超过1这么一个判断条件,通过左旋转、右旋转来调整,从而保证树的高度平衡!

对于红黑树,其实也是一样的,对于插入、删除操作,主要也是通过左旋转、右旋转来进行调整,相比平衡二叉树,红黑树因为节点有颜色标签,多了一个颜色转变操作!

同理,我们只需要分析出哪些场景下需要进行调整,即可总结出算法,从而写出实践代码!

废话也不多说来,下面我们一起来分析一下红黑树,在插入、删除操作时,应该怎么处理!

2.1、插入场景

将一个节点插入到红黑树中,需要执行哪些步骤呢?

  • 第一步:将红黑树当作一颗二叉查找树,将节点插入树的底部;
  • 第二步:默认将插入的节点着色为红色,如果是根节点,颜色着为黑色;
  • 第三步:通过一系列的旋转或着色等操作,使之重新成为一颗红黑树;

对于第一步,比较好理解,红黑树其实就是二叉树的一种特殊形态的树形结构,先找到合适的位置,然后将节点插入到树上。

图片

对于第二步,为什么新插入的节点要设置为红色呢?

因为插入之前所有根至外部节点的路径上黑色节点数目都相同,所以如果插入的节点是黑色,肯定会导致黑色节点数目不相同!

而相对的插入红节点可能也会违反不能出现两个连续的红节点,如果违反条件,直接进行颜色转换或者旋转操作即可!

相对将插入的节点着色为黑色,红色操作可能更简单些! 因为根节点为黑色,如果是新插入的节点为根节点,直接将颜色设置为黑色!

既然新插入的节点为红色,那么我们就继续来分析一下,新插入节点的场景,例如:

  • 1.插入的节点,父亲为黑色;
  • 2.插入的节点,父亲为红色;

当新插入的节点的父亲为黑色时! 因为新插入的节点为红色,因此不会违反任何特性!

图片

当新插入的节点的父亲为红色时! 因为新插入的节点为红色,违反不能出现两个连续的红节点,因此需要进行调整!

图片

这种场景有3种调整情况,为了便于下面分析,假设将新插入节点用z代替,z的父节点用a代替,a的父节点用c代替,z的叔节点用y代替,如下:

图片

情况1:z的叔节点y是红色的

case1调整过程如下:

图片

调整说明: 因为 节点 z 是一个红色节点,其 父节点 a 是红色的,违反了特性4,因此需要进行调整。因为其 叔节点 y 是红色的,于是可以修改 节点 a节点 y 为黑色,此时 节点 c 的黑高会发生变化,由原来的黑高1变成黑高2,为了节点 c 保持黑高不变,将其变成红色。

此时,由于 节点 c 由黑色变成了红色,如果 节点 c 的父节点是红色,也会违反特性4,继续将 节点 c 看成是 节点 z向上回溯调整树

需要注意的是: 对于新插入的 节点 z节点a 的左子树的情况,操作与上述一致;对于新插入的 节点 z节点 c 的右子树的节点的情况,操作与上述对称!

情况2:z的叔节点y是黑色,且z是一个左孩子

case2调整过程如下:

图片

调整说明: 这种情况,并不能像上面那样改变节点颜色就可以满足要求,因为如果将节点z 的父节点 a 变成了黑色, 那么树的黑高就会发生变化,必然会引起对性质5的违反。比如,此时节点y为黑色, 节点c 的右子树高度为2(忽略子树),左子树高也相同,如果简单的修改节点a 为黑色,那么节点c 的左子树的黑高会比右子树大1, 此时即使将节点c 修改为红色也于事无补!

因此,单靠颜色转变无非解决问题,需要进行旋转调整。先绕 节点 a 的父节点进行右旋转,再将 节点 a节点 c 的颜色进行互换!最终结果与插入前一致!

需要注意的是: 对于新插入的 节点 z节点 c 的右子树的节点的情况,操作与上述对称!

情况3:z的叔节点y是黑色,且z是一个右孩子

case3调调整过程如下:

图片

调整说明: 当节点 z 是一个右孩子时,先绕节点 a 进行左旋转,之后树的形态就变成如上面介绍的情况2,再进行右旋转、颜色转变,即可实现红黑树的特性!

需要注意的是: 对于新插入的 节点 z节点 c 的右子树的节点的情况,操作与上述对称!

以上就是红黑树新增节点时,所有可能的操作以及调整方式!

可以得出如下结论:对插入节点后的调整所做的旋转操作不会超过2次!

2.2、删除场景

我们继续来看看删除场景,对于二叉查找树操作,我们知道有如下步骤:

  • 当删除节点,只有左子树时,将右子树向上移动;
  • 当删除节点,只有右子树时,将左子树向上移动;
  • 当删除节点,有左、右子树时,通过找到删除节点的右节点的最末端左子树,也就是后继节点,进行替换并删除;

二叉查找树删除过程图:

图片

红黑树的操作也是如此,步骤如下;

  • 第一步:将红黑树当作一颗二叉查找树,将节点删除;
  • 第二步:通过旋转和变色等一系列来修正该树,使之重新成为一棵红黑树;

在第一步中,首先我们重点要弄清楚什么是删除节点?

这个删除节点,某些情况下并非我们真正传入的删除值,对于拥有左子树、右子树的节点来说,删除节点指的是被删除节点的后继节点或者前驱节点

可能有点绕,例如上图中拥有左子树、右子树的删除场景,我们传入需要删除的节点是 80,但是实际上 删除节点的是85节点(85是一个叶子节点),然后将80节点内容替换成85,做了一个偷天换日的操作

因此无论对于哪种情况,我们可以得出结论:删除节点一定是一个单分支节点或者叶子节点了解这个结论对于后面我们的红黑树删除过程分析会非常有用

清楚删除流程之后,剩下的重点就是如何进行修正,以满足红黑树的特性,那么,哪些场景下的删除需要进行调整,我们一起来看一下!

2.2.1、删除的节点为红色

当删除的节点为红色时,这种情况直接将删除节点移除,理由如下:

  • 树中各个节点的黑高没有变化;
  • 删除后满足性质4,因为不会出现 红红相连 的情况;
  • 删除的不可能是根节点,因为根节点是黑色的;
2.2.2、删除的节点为黑色

当删除的节点为黑色时,因为删除节点的父节点失去了一个黑色子节点,这种情况会导致左右子树不平衡,因此需要进行调整,假设x为被删节点的替换节点,也就是说:

  • 当被删节点的左子树为空时,x为被删节点的右孩子;
  • 当被删节点的右子树为空时,x为被删节点的左孩子;
  • 当被删节点的左、右子树都为空时,x是空节点(即删除的是终端节点);
  • 当被删节点的左、右子树都不为空时,x为被删节点的右子树的最末端的左子树,也就是中序遍历直接后继的右孩子;

wx的兄弟节点,有以下几种情况!

1)x的兄弟节点w是红色的

case1调整过程如下:

图片

调整说明: 因为 节点 c 的左子树被删去了一个黑色节点,导致节点 c 的左子树黑高少了1,所以节点c 是不平衡的。可以对节点c 进行一次左旋,然后修改节点80和节点120的颜色。

此时,x的父亲节点c依然不平衡,节点x 的兄弟节点w 变成黑色的

继续看下面的分析,这种不平衡由下面的几种情况进行处理!

2)x的兄弟节点w是黑色的,并且w的两个子节点都是黑色的

当x的兄弟 节点 w 是黑色的,并且w的两个子节点都是黑色的时,此时需要分两种情况!

情况2.1:x的父节点为红色

case2.1调整过程如下:

图片

调整说明: 在删除节点后,左图 节点 c 不平衡,节点c 左子树的黑高为hl+1,节点c 左子树的黑高为hr+2,左子树黑高小于右子树黑高。因此直接将节点c 修改为黑色,节点 w 修改为红色,此时的黑高又恢复如初!但是节点c 作为子节点,因为黑高减少,需要 继续向上回溯调整 树的黑高,此时节点c 作为新的节点x。

情况2.2:x的父节点为黑色

case2.2调整过程如下:

图片

调整说明: 只需要将 节点 w 修改为红色,继续向上回溯调整树的黑高,此时 节点 c 作为新的 节点x

3)x的兄弟节点w是黑色的,并且w的右孩子是红色的

当x的兄弟节点w是黑色的,并且w的右孩子是红色的,此时也需要分四种情况!

情况3.1:x的父节点为黑色,w的左孩子是黑色的

case3.1调整过程如下:

图片

调整说明: 因为删除节点导致节点c 不平衡,对节点c 进行一次左旋转,将节点w 的右孩子颜色修改为黑色。此时节点c 已经达到平衡,同时节点w 也达到平衡,整棵树已经平衡了!

情况3.2:x的父节点为黑色,w的左孩子是红色的

case3.2调整过程如下:

图片

调整说明: 同样的,对节点c 进行一次左旋转,将节点w 的右孩子颜色修改为黑色。此时节点c 已经达到平衡,同时节点w 也达到平衡,整棵树已经平衡了!

情况3.3:x的父节点为红色,w的左孩子是黑色的

case3.3调整过程如下:

图片

调整说明: 对节点c 进行一次左旋转,将节点 w 的右孩子颜色修改为黑色,同时将节点80 和节点100 颜色进行互换。此时节点c 已经达到平衡,同时节点w 也达到平衡,整棵树已经平衡了!

情况3.4:x的父节点为红色,w的左孩子是红色的

case3.4调整过程如下:

图片

调整说明: 同样的,对节点c 进行一次左旋转,将节点 w 的右孩子颜色修改为黑色,同时将节点80 和节点100 颜色进行互换。此时节点c 已经达到平衡,同时节点w 也达到平衡,整棵树已经平衡了!

4)x的兄弟节点w是黑色的,而且w的左孩子是红色的,w的右孩子是黑色的

当x的兄弟节点w是黑色的,而且w的左孩子是红色的,w的右孩子是黑色的,此时也需要分2种情况!

情况4.1:x的父节点为红色

case4.1调整过程如下:

图片

调整说明: 对节点w 进行一次右旋转,将节点90和节点100 进行颜色互换,此时节点x 和节点w 的关系变成: x的兄弟节点w是黑色的,并且w的右孩子是红色的。此时按照case3.3情况进行处理即可!

情况4.2:x的父节点为黑色

case4.2调整过程如下:

图片

调整说明: 同样的,对节点w 进行一次右旋转,将节点90和节点100进行颜色互换,此时节点x 和节点w 的关系变成:x的兄弟节点w是黑色的,并且w的右孩子是红色的。此时按照case3.1情况进行处理即可!

删除的场景相比插入要多很多,情况也比较复杂,但是基本有自己的规律,我们只需要把规律总结出来,然后就可以用逻辑代码来实现!

需要注意的是: 此次节点x 位于节点c 的左子树,如果位于右子树,操作与之对称!

可以得出如下结论:对删除节点后的调整所做的旋转操作不会超过3次!

 

三、总结

本篇文章,前前后后写了大概一个星期,尤其是删除逻辑,比较复杂,如果有理解不对的地方,欢迎网友们指出!

以下是红黑树总结:

  • 1、红黑树是一个基本平衡的二叉树,在查询方面,与二叉查找树思路相同;在插入方面,单次回溯不会超过2次旋转;在删除方面,单次回溯不会超过3次旋转!
  • 2、相比于平衡二叉树,红黑树在查询、插入方面,效率差不多;在删除方面,平衡二叉树最多需要log(n)次变化,以达到严格平衡,而红黑树最多不会超过3次变化,因此效率要高于平衡二叉树!
  • 3、在实际应用中,很多语言都实现了红黑树的数据结构,比如 Java 中的 TreeMap、 TreeSet,以及 jdk1.8 中的 HashMap!

http://chatgpt.dhexx.cn/article/asXQNJ1O.shtml

相关文章

红黑树解读与Java实现

红黑树解读与Java实现 概要 目录 红黑树的介绍红黑树的应用红黑树的时间复杂度和相关证明红黑树的基本操作,左右旋红黑树的基本操作,添加与调整红黑树的基本操作,删除与调整 一、红黑树的介绍 什么是红黑树? R-B Tree&#…

JDK14的新特性:JFR,JMC和JFR事件流

文章目录 简介JFRJMC创建JFR分析JFR JFR事件JFR事件流总结 简介 Java Flight Recorder(JFR)是JVM的诊断和性能分析工具。它可以收集有关JVM以及在其上运行的Java应用程序的数据。JFR是集成到JVM中的,所以JFR对JVM的性能影响非常小&#xff0…

Cocos2d-x利用jni调用java层代码

jni的意思是java本地调用,通过jni可以实现java层代码和其他语言写得代码进行交互。在cocos2d-x中,如果想要在c层调用java层的代码,就是通过jni技术。通过调用java层的代码,我们就可以在Android平台下实现一些引擎没有提供给我们的…

红黑树,学习红黑树,jdk1.8之后的新知识

红黑二叉树 1.引言 HashMap的基本结构是数组,链表和红黑树。以数组为基本形态,数组中的元素先以链表形式储存,当链表的长度超过8时(包含数组上的那个链表头)就会将链表转换为红黑树,以加快修改和查询效率…

JavaScript 红黑树

一、树的平衡性 为了能以较快的时间O(logN)来操作一棵树,我们需要保证树总是平衡的: 至少大部分是平衡的,那么时间复杂度也是接近O(logN)的也就是说树中每个节点左边的子孙节点的个数应该尽可能的等于右边的子孙节点的个数.常见的平衡树有哪些呢?AVL树: AVL树是最早的一种平衡…

最详细的对红黑树性质理解

红黑树的性质: 在了解红黑树之前,建议先去了解一下什么是二叉搜索树。 因为红黑树属于二叉搜索树特殊的分支,所以建议先去了解一下二叉搜索树。 二叉搜索树:https://blog.csdn.net/Falling_stars_/article/details/115536511 红…

JDK1.8之后,HashMap转变红黑树

当链表长度大于8并且数组长度大于64时,才会转换为红黑树 根据源码注释: 1.TreeNodes占用空间是普通Nodes的两倍。 只有当bin(bin就是bucket-桶,即HashMap中hashCode值一样的元素保存的地方)包含足够多的节点时才会转成…

jdk1.8的HashMap中的红黑树插入,为什么是红黑树而不是AVL树

jdk1.8HashMap的源码 树节点 static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {TreeNode<K,V> parent; // red-black tree linksTreeNode<K,V> left;TreeNode<K,V> right;TreeNode<K,V> prev; // needed to unli…

浅谈红黑树

这篇文章的删除操作参考这篇博客博客地址 聊红黑树之前我想先来谈谈B树&#xff08;多路平衡查找树&#xff09;&#xff0c;为什么来聊这个东西呢&#xff0c;其实红黑树就是一个B树。了解B树后对红黑树的理解会比较有帮助。 首先是2、3、4节点。 红黑树中单个黑节点对应B树中…

红黑树的理解与代码实现

红黑树 我们知道对于二叉搜索树而言&#xff0c;无法保证树的平衡性&#xff0c;从而使得进行操作的时候时间复杂度在O(logn)与O(n)之间。这样是不稳定的。而2-3树则借助于3-结点和临时的4-结点&#xff0c;通过分解&#xff0c;解决了平衡问题。例如对于插入&#xff0c;在最终…

图解TreeMap的红黑树平衡操作fixAfterInsertion(),接着手撕红黑树添加节点

一、前言 啥也不想说&#xff0c;就卷、卷技术&#xff1b;手撕红黑树搞起。 1、红黑树简介 红黑树就是一种平衡的二叉查找树&#xff0c;其有五个特点&#xff1a; 1.每个节点要么是红⾊&#xff0c;要么是⿊⾊&#xff1b; 2. 根节点⼀定是⿊⾊的&#xff1b; 3. 每个叶⼦…

有人在jdk源码里下毒【class.newInstance() bug复现】

如图 在用反射的时候&#xff0c;发现这个方法被idea划横杠了 稍加思索后发现是这方法从jdk9开始弃用了&#xff0c;倒不影响使用&#xff0c;对象还是能正常射出来&#xff0c;就是看着很难受 &#xff08;最近刚把本地开发机从8升到11&#xff0c;难怪&#xff09; 说下我…

红黑树理解以及Java实现

红黑树本身并不复杂&#xff0c;只是在插入删除的时候情况比较多&#xff0c;如果强行记忆的话会显得比较困难&#xff0c;而且容易忘记。所以以前对红黑树一直没有很好的掌握。恰好这次借着复习数据结构的机会&#xff0c;静下心来仔细的学习了一下红黑树&#xff0c;并用Java…

Java 9 vs Java 8:引入模块化和JShell的全面升级

Java 9 是 Java 语言的一个重大版本升级&#xff0c;带来了许多新的特性和改进。 在本篇博客中&#xff0c;我将为您介绍 Java 9 的一些重要特性。 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; 目录 一、模块化二、JShell三…

HashMap 在 JDK 1.8 后新增的红黑树结构

读完本文你将了解到&#xff1a; 点击查看 Java 集合框架深入理解 系列 - - 乾杯传统 HashMap 的缺点HashMap 在 JDK 18 中新增的数据结构 红黑树HashMap 中关于红黑树的三个关键参数HashMap 在 JDK 18 中新增的操作桶的树形化 treeifyBinHashMap 在 JDK 18 中新增的操作 红黑树…

epoll底层红黑树使用部分源码剖析:为什么使用红黑树以及如何使用红黑树

我们知道epoll的底层使用了红黑树来管理文件描述符&#xff0c;为什么会选择红黑树这种结构呢&#xff1f; 以下是个人理解&#xff1a; epoll和poll的一个很大的区别在于&#xff0c;poll每次调用时都会存在一个将pollfd结构体数组中的每个结构体元素从用户态向内核态中的一…

HashMap在jdk1.8为何引入了红黑树?

原创不易,麻烦点个关注,点个赞,谢谢各位。 二叉查找树 二叉查找树,也称有序二叉树(ordered binary tree),或已排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若任…

从电路的角度理解特征阻抗

传输显得特征阻抗不是真实的电阻&#xff0c;微波技术课程会从波的角度描述特征阻抗&#xff0c;这次试图从电路的角度来理解 无损传输线是分布的L C 网络&#xff0c;假设是无限长传输线 从a,b两点看入的阻抗是相等的&#xff0c;所以可以简化成下图&#xff1a; 化简可得 这…

同轴电缆阻抗总结(电阻、阻抗、特性阻抗)

文章目录 同轴电缆电阻、阻抗、特性阻抗电阻阻抗&#xff08;Impedance&#xff09;特性阻抗 总结 同轴电缆 同轴电缆是一种电线及信号传输线&#xff0c;一般是由四层物料造成&#xff1a;最内里是一条导电铜线&#xff0c;线的外面有一层塑胶&#xff08;作绝缘体、电介质之…

传输线阻抗方程的推导

在传输线理论中&#xff0c;当一段特征阻抗为 Z 0 Z_0 Z0​ 的传输线的终端连接了一个阻抗为 Z L Z_L ZL​ 的负载时&#xff0c;看向这段传输线的输入阻抗 Z i n Z_{in} Zin​ 将不再是 Z 0 Z_0 Z0​。 传输线阻抗方程 (Transmission Line Impedance Equation) 就是计算…