红黑树与平衡二叉树的相同之处与不同之处

news2024/9/22 9:34:13

红黑树很多资料上写的非常繁杂,初次接触真的难以理解。写本文也就是为了记录一些思考和想法,并不会记录如何使用代码实现。

不记录代码还有个原因:黑红树的算法就是根据各种情况进行一些操作,情况很复杂,分插入的和删除的,有的是资料记录这些,但是为什么要进行这些操作,为什么这些操作那么像但又略有不同却没多少人说明清楚。所以本文主要是记录想法的。

平衡树的作用

红黑树是平衡二叉树的一种,自然也是平衡树的一种。那平衡树是干什么的呢?

平衡树在很多教材的介绍都是限制子节点的高度差,保持树的平衡(根节点的左、右子树差不多大)。但其实仔细想想,这就是在尽量减少树的高度,直到最小(左右高度差最大为 1 嘛)。

为什么要减少树的高度呢?

树往往用来表示一个动态集合,集合不光有元素,也有元素之间的关系,还有对元素的操作,比如增、删、查。(树很少有“改”的情况,执行改的效率不如执行等价操作:删和增)

因为无论是删和增,还是查,都是按照树的结构,从根往下走,范围越来越小,只涉及一个子树。而改的时候,可能要从一个子树到另外一个子树。

而这些操作与树的高度有关。因为我们常说的树其实是一个有向图:父节点和子节点,二者是有顺序的。那么从根节点出发,进入每一个子树之后,就和其他的子树无关了,直到叶节点结束。

所以,降低树的高度,可以加快这些操作的平均时间。

红黑树又是干嘛的

红黑树相比平衡二叉树,对于高度的限制没有那么严苛,不考虑总高度,而是考虑黑节点和红节点之间的关系。放宽限制,会使得操作节点(增删改)的时候所需的时间减少许多。如下是算法导论中的一个红黑树,可以很明显看到高度差超过 1 不少:

请添加图片描述

红黑树要满足以下条件:

  • 节点是红色或黑色(不然怎么叫红黑树)。
  • 根节点是黑色。
  • 所有叶节点(也就是最终的NIL节点)是黑色。
  • 红色节点的子节点必须是黑色(红下一个必是紫,但是黑的下一个可红可黑)。
  • 从任一节点到其每个叶子节点的所有路径上必须具有相同数量的黑色节点(这话不理解没关系,下面解释完你就懂了)。

红黑树的绝大部分操作都是在维持上述性质,真正操作所需的时间并不多。所以这个性质是红黑树的核心。

最后那句很绕到话其实就是红黑树的最重要的概念:黑高。

黑高:一个节点到叶节点的简单路径中,黑节点的总数。
所谓简单路径就是不重复、没有回路(树本身就没回路)。

什么意思呢,就是说任何一个节点到最后的NIL节点的时候,中间经过的黑节点数量必须一样。这就是放宽之后的限制,黑高也就是红黑树的限制

由于NIL节点也是黑的,所以所有非叶节点的黑高至少为 1,而叶节点(NIL节点)的黑高为 0。但是要注意,比如上图中最左边的7,自己是黑的,但是黑高为 1(不算自己,只算叶节点)。

为什么要弄黑高这么个玩意呢?

请你看一个非常简单的红黑树:
请添加图片描述

现在,把这棵树所有黑色节点和它的红色子节点写成一个节点,NIL节点就是最后的“小脚”:

请添加图片描述

这里没有出现 4 个“小脚”的情况属于特殊,你看看图会发现如果一个黑节点有两个红子节点,那么就会出现 4 个小脚。

这时候你会发现,在这种画法下,NIL节点前的一个节点必然有2、3 或 4 个NIL节点。这就是很多资料中写到的 2-3-4 树

此外,画成这样,你可以很清楚的看到黑高的作用,因为我们将黑高一样的关联的黑红节点放到一起了。

红黑树上的操作

在理解上面的** 2-3-4 树**之后,如何进行一系列操作就是易如反掌了。查就是二叉排序树(BST)的算法,因为并不需要维护红黑树的性质,所以这里就不说了。

增(插入)

插入算法的思路就是:

插入新元素
重新着色
旋转树
重新着色
旋转树

后面四个步骤,两两组合就是为了修复(维护)红黑树的性质。所以请记住重新着色-旋转这个组合操作是维护红黑树的非常重要的步骤(后续你可以看到)。

重新着色
旋转树
插入

插入首先按照树找到插哪里,因为平衡树本身就有搜索的能力,比如下面的这个树,我们插入4,设置为红色,根据树搜索发现插入位置在z处,这是当前操作处x(由于根据设计需要看叔节点,所以有个y指针指向叔节点):

请添加图片描述

为什么设计为红色后面会解释。

写成** 2-3-4 树**如下:
请添加图片描述
会发现红色处的“小脚”数量不对,原来是 4 个,但是插入后却应该是 5 个,也就是多了一个脚出来,说明此处需要对树进行调整了。

要知道红黑树在插入之前是完全符合性质的,也就是说,插入节点的父、叔节点的父节点,必然是黑的。如果当初插入的时候,4设置为黑的,那么** 2-3-4 树**就没有问题啦,也就是说这棵树没有符合黑高的要求。
但是在这种情况下,树的高是最小的嘛?别忘了我们搞黑红树的目的,就是为了在高度差限制较松的情况下,尽量减少树的高度。
所以新插入的节点必须是红色的。

调整分两步:

  • 调整为合适的颜色;
  • 调整为合适的位置。

多一个脚,就将4/5/7/8这个节点拆成两个子树,言外之意就是要有 2 个黑节点了。这里你可以自己想想更改方法,发现不唯一。

你后续可能会注意到:维护黑高的性质就是通过重新着色做到的,而旋转是为了“红色节点的子节点必须是黑色”这个性质。

第一次重新着色-旋转

在这种情况下,红黑树的要求是看插入位置的叔节点(父节点的兄弟节点)的颜色,如果插入点的叔节点也是红的,那么父节点和叔节点全改为黑的,原本是黑的爷节点改为红

请添加图片描述
这个时候会发现,往上又不对了:此时看7的叔节点14,发现是黑的,与父节点2的颜色不同。和上面的情况不一样了。

此时是7是因为下面的已经处理好了,符合性质了,所以往上走了。

这时候再画个** 2-3-4 树**:

请添加图片描述

第二次重新着色-旋转

这个时候黑高已经最小了,但树高并没有变化,而且还违反性质。根据规定,此时需要对整棵树进行一次左旋(因为7在右边,再往右没啥用)。左旋后如下:

请添加图片描述

此时继续重复操作,发现和上面的情况一样,叔节点14的颜色和父节点7不同,那么此时由于27的左边中,所以整棵树右旋,并且父节点7和爷节点11交换颜色,结果如下:

请添加图片描述

此时你会发现树高从 5 变成了 4,而且完美符合红黑色性质,插入这才算结束了。

“父节点7和爷节点11交换颜色”是为了使得这部分子树的根节点为黑的。不过在上图中,很巧合地是整棵树的根节点。

所以你可以看到,两次重新着色-旋转就维护好了红黑树的性质。第一次是维护黑高的性质,第二次是维护“红色节点的子节点必须是黑色”这个性质。

删除

删除同样需要维护上述性质。关于修改颜色方面,其实就是保持黑高。同样当(子)树左边重就右旋,右边重就左旋。使得树尽量平衡。

删除有一点不同:以下图(来自https://iq.opengenus.org/red-black-tree-deletion/)为例,虽然删除了10,但是依旧要处理10的关系,所以需要一个辅助指针替代10,这里记为NULL。()

请添加图片描述

可以看到删除完之后,右边重,就左旋。左旋完之后,要维持黑高的性质,就修改(互选)颜色。只不过在删除的时候,父、子、叔、爷的颜色和位置情况比较多,所以你会发现很多算法书都是按照情况进行介绍的。

这些情况你写代码的时候看书就行了,为什么要换颜色和旋转那样很多教材中并没有点透。这点算法导论中虽然没说,但是课上确实说了。

希望能帮到有需要的人~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1977026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构 二叉树和堆总结

树 概念 树是一种层次结构非线性的数据结构,其是由节点和边组成,可以用来表示层次关系的数据。 树的相关概念 节点:树的基本组成单位,每个节点都包含数据,同时与其他节点相互连接根节点:树的顶层节点&…

SpringBoot_第十一章(Thymeleaf模板引擎)

目录 1:什么是Thymeleaf模板引擎 2:springboot怎使用Thymeleaf 2.1:导入pom文件 2.2:查看ThymeleafAutoConfiguration 3:Thymeleaf核心语法 4:使用Thymeleaf 5:具体语法练习 1&#xff1a…

数据集划分方法

数据集划分是机器学习和数据科学中的一个重要步骤,主要目的是为了确保模型的有效性和可靠性。 留出法(简单交叉验证) 将数据集划分为互斥的子集:训练集和测试集。 训练集: 用于训练模型。 测试集: 用于评估模型的性能和验证其准确…

图神经网络揭秘:视觉和实用指南

目录 一、说明 二、图如何网络化? 三、你需要知道的 3.1 进入图神经网络 3.2 消息传递 3.3 我们如何处理最终的向量表示? 四、图神经网络,总结 4.1 为什么选择图形神经网络? 4.2 简而言之 一、说明 了解图神经网络的世界&#xff…

C#中投影运算的深入解析与实例应用

文章目录 1、投影运算的基本语法2、投影运算的高级用法3、投影运算在向量空间中的运用4、投影运算在数据库和XML中的实际应用5、投影运算能用于哪些实际场景?6、结论 在C#编程中,投影运算是一种常用的数据操作技术,它可以将一个数据集合转换成…

开放式耳机推荐?时尚潮流品牌:悠律ringbud pro开放式耳机实测测评

作为一位音乐发烧友,什么类型的耳机都体验过,有些几百上千的耳机音质还是差点意思,还是会有听久了感觉不舒服的情况,低音量感不够的问题,直到用了悠律ringbud pro开放式耳机,才算真正打开新世界的大门&…

C语言程序设计-[2] 数据类型、常量和变量

1、数据类型 C语言支持的数据类型如下: 2、常量 常量就是不同数据类型下的值。这里主要讲整型、实型和字符型常量。 (1)整型常量:用十进制、八进制和十六进制三种形式表示。 (1)实型常量:由整…

HCIP实验-MGRE

实验拓扑: 实验要求: 1.R2为ISP,其上只能配置IP地址 2.R1-R2之间为HDLC封装 3.R2-R3之间为PPP封装,pap认证,R2为主认证方 4.R2-R4之间为PPP分装,chap认证,R2为主认证方 5.R1、R3、R4构建MG…

unity拖拽物品遇到的bug及解决思路

记录一下拖拽实现过程中遇到的bug RectTransform 专门用在UI中transform 判断点击是否在UI中 使用这个函数就可以判断点击的是否是UI面板,返回true表明在UI面板中 EventSystem.current.IsPointerOverGameObject()值得一提的是,如果发现了有UI穿透效…

【C语言】分支与循环(分支篇)

前言 C语言是一种结构化的计算机语言,这里指的通常是顺序结构、选择结构、循环结构,掌握这三种结构之后我们就可以解决大多数问题。 分支结构可以使用if、switch来实现,而循环可以使用for、while、do while来实现。 1. if语句 1.1 if if…

【滴水三期】32/64位——PE文件节表打印与解析

【作业内容】 1、手动查&#xff0c;画个PE文件图。 2、编写程序打印节表中的信息。 3、根据节表中的信息&#xff0c;到文件中找到所有的节&#xff0c;观察节的开始位置与大小是否与节表中的描述一致 【PE file_buffer文件图】 【IMAGE_SECTION_HEADER解析】 <winNT.h…

web浏览器播放rtsp视频流,海康监控API

概述 这里记录一下如何让前端播放rtsp协议的视频流 ​ 项目中调用海康API&#xff0c;生成的视频流(hls、ws、rtmp等)通过PotPlayer播放器都无法播放&#xff0c;说明视频流有问题&#xff0c;唯独rtsp视频流可以播放。 但是浏览器本身是无法播放rtsp视频的&#xff0c;即使…

Qt3D给圆环等立体图形添加纹理图片

添加纹理图片&#xff0c;首先需要自己找一个纹理图&#xff0c;当然了&#xff0c;随便什么图片都行。 创建3D图形的主要步骤查看另一篇文章。 这里主要代码如下&#xff1a; 使用QTextureLoader加载图片&#xff0c;图片路径需为qrc:/的路径。 auto *planeTransform1 ne…

PyMongo

什么是PyMongo PyMongo 是一个 Python 库&#xff0c;用于与 MongoDB 数据库进行交互。MongoDB 是一个基于文档的 NoSQL 数据库&#xff0c;提供高性能、可扩展性和灵活的架构。PyMongo 提供了一套工具&#xff0c;使得在 Python 程序中操作 MongoDB 变得简单和高效。 安装PyMo…

【C++程序设计】——利用数组处理批量数据(二)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-削好皮的Pineapple! &#x1f468;‍&#x1f4bb; hello 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 削好皮的Pineapple! 原创 &#x1f468;‍&#x1f4…

17085 工作分配问题(优先做)

这个问题可以通过回溯法来解决。我们可以遍历所有可能的工作分配方案&#xff0c;然后找出总劳务费用最小的方案。 以下是C代码实现&#xff1a; #include <iostream> #include <vector> #include <algorithm> using namespace std;const int INF 1e9; co…

羌活基因组--文献精读-36

The chromosome-scale assembly of the Notopterygium incisum genome provides insight into the structural diversity of coumarins 羌活&#xff08;Notopterygium incisum&#xff09;基因组的染色体级别组装为香豆素的结构多样性提供了新的见解 摘要 香豆素是由苯丙素途…

内网安全:多种横向移动方式

1.MMC20.Application远程执行命令 2.ShellWindows远程执行命令 3.ShellBrowserWindow远程执行命令 4.WinRM远程执行命令横向移动 5.使用系统漏洞ms17010横向移动 DCOM&#xff1a; DCOM&#xff08;分布式组件对象模型&#xff09;是微软的一系列概念和程序接口。它支持不同…

Java中操作文件

认识⽂件 我们先来认识狭义上的⽂件(file)。针对硬盘这种持久化存储的I/O设备&#xff0c;当我们想要进⾏数据保存时&#xff0c; 往往不是保存成⼀个整体&#xff0c;⽽是独⽴成⼀个个的单位进⾏保存&#xff0c;这个独⽴的单位就被抽象成⽂件的概 念&#xff0c;就类似办公桌…

【Linux】深入理解线程

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…