红黑树的理解与 Java 实现

YOLO26一文弄懂 | YOLO26内容详解、网络结构解读 、yolo26.yaml配置文件详细解读与说明、YOLO26虚拟环境安装、模型训练、验证、推理参数详细解析 | 通俗易懂!入门必看系列! YOLO26目标检测模型创新与应用指南 本文全面介绍了YOLO26目标检测模型的创新特性、网络结构及实践应用。YOLO26基于四大核心原则设计:简洁性(移除NMS后处理)、部署效率(端到端架构)、训练创新(MuSGD优化器)和任务优化(支持多种视觉任务)。模型包含五种尺寸规格,CPU推理速度提升43%,支持目标检测、实例分割、姿态估计等任务。 文章详细解析了YOLO26的网络结构(Backbone-Neck-Head三部分)和yaml配置文件,提供了从虚拟环境配置到模型训练、验证、推理的完整教程。 阅读详情

点击上方“芋道源码”,选择“设为星标”

做积极的人,而不是积极废人!

源码精品专栏

 

来源:xyk_1021

blog.youkuaiyun.com/weixin_42786274/article/details/86557922

  • 前言

  • 红黑树的性质

  • 红黑树的操作

    • 1. 查找操作

    • 2. 插入操作

    • 3. 删除操作

  • Java实现

  • 总结


前言

前段时间在研究 JDK1.8 的 hashmap 源码,看到 put 方法的插入环节,遇到了红黑树,不得不停止阅读源码的过程,因为还没掌握红黑树是无法完全读透 hashmap 源码的。红黑树作为一种数据结构,它被应用得非常多,可能很多人不认识它,但其实它已经在默默为我们的代码在发光发热。例如,你只要在 Java 中用到 map,基本上就是在用红黑树(当元素个数到达八个时链表转红黑树)。

PS:在看这篇文章前,必须先了解普通的二叉查找树和平衡查找树(AVL)树、2-3-4树。不然看起来会非常吃力。

红黑树的性质

红黑树是一种自平衡树,它也是一颗二叉树。既然能保持平衡,说明它和 AVL 树类似,在插入或者删除时肯定有调整的过程,只不过这个调整过程并不像 AVL 树那样繁琐。为何红黑树使用得比 AVL 树更多,就是因为红黑树它的调整过程迅速且简介。红黑树有以下五个特性:

  • 性质1:节点是红色或黑色

  • 性质2:根是黑色

  • 性质3:所有叶子都是黑色。叶子是 NIL 节点,也就是 Null 节点

  • 性质4:如果一个节点是红的,则它的两个儿子都是黑的

  • 性质5:从任一节点到其叶子的所有简单路径都包含相同数目的黑色节点。

下图展示了一棵红黑树。

分析:

注意理解上,叶子并不等价于黑色节点,但是他们的颜色都是黑色。

为何要给节点指定红或者黑的颜色?

作者这种设计,只是为了从编程上达到一种便利的效果。另外可以让它们在插入时达到近似的平衡,并不像 AVL 树那样绝对平衡。实际上,红黑树是2-3树的一种变体,某种情况下,它又相当于2-3-4树。因为2-3树在编程上需要比较多的代码量,所以诞生了红黑树这种巧妙的设计。通过加了颜色来区分结点,这样编程上就可以当成二叉树来写程序,不用分别用三个指针表示左、中、右孩子了。

看一下红黑树和2-3树的等价性联系

从上面可以看到,把红色节点放到与父亲齐平,就是2-3树中的一个2-3节点。

红黑树的操作

数据结构的性质看完之后,就要掌握它到底会存在哪种操作?例如 hashmap,它最常见的操作就是 get 和 put、扩容。同理,红黑树也有它的基本操作。因为它本身上也是一棵二叉查找树,所以重点关注的操作无非就是查找、插入、删除。

1. 查找操作

红黑树的查找方式很简单,只要是树,查找的过程无非就是一个递归过程。如果查找的元素小于当前节点,那么查找其左子树;如果查找的元素大于当前元素,则查找其右子树。

2. 插入操作

插入操作首先需要通过查找操作找到合适的插入点,然后插入新节点。如果在插入节点后,发生了违背红黑树特性的情况时,需要对红黑树进行旋转染色等操作,使其重新满足特性。

2.1 插入新节点

为了在插入新节点时尽可能少的违反红黑树特性且更容易调整红黑树,就先将新节点染成红色。这样就只可能会违反特性4。如果这里没有违反特性4,那么就不需要对红黑树进行调整,插入操作完成。

2.2 调整子树

那么,在违反了特性4的时候,新节点的父节点为红色节点。根据特性2可知,父节点不是根节点,则新节点必有祖父节点。又根据特性3可推论出红色节点必有两个黑色子节点(空节点为黑色)。此时会出现两种情况:叔节点为红色、叔节点为黑色。

图例:C 表示当前节点,P 表示父节点,U 表示叔节点,G 表示祖父节点

(1)父节点与叔节点都为红色的情况

在这种情况下,需要将父节点和叔节点变为黑色,再将祖父节点变为红色。这样,图上所展示的子树就满足了红黑树的特性。如下图所示。

但是这里又可能会产生新的违反特性情况,因为祖父节点变成了红色,那么它可能会造成违反特性4的情况。所以,这里就将祖父节点作为当前节点,进行新一轮的调整操作。

(2)父节点为红色,叔节点为黑色的情况

在这种情况下,对其调整的核心就是保持父节点分支符合特性4,而叔节点分支保持符合特性5。

  • 第一步,旋转。对祖父节点进行左旋或者右旋。如果父节点是祖父节点的右子节点,那么对祖父节点进行左旋;否则,对祖父节点进行右旋。

  • 第二步,染色。将祖父节点染为红色,而父节点染为黑色。

进过这两步,上图的情况会转换为下图所示。

可以看出,父节点这一分支进过调整后,当前节点与父节点的颜色不再是连续红色,满足特性4。而叔节点这一分支的黑色节点数目没有发生变化,满足特性5。对原祖父节点的父节点来说,该子树没有发生违反特性的变化。该子树调整完成。

2.3 检查根节点

当上述调整执行完后,还有最后一步,就是检查是否满足特性2。这一步只需要将根节点染成黑色就可以,无需再多加判断。

3. 删除操作

需要重点理解的就是删除操作,这个也是我觉得是红黑树中最难的部分。

删除操作要比插入操作略微复杂一些。因为删除的节点可能是出现在树的中间层的节点,此时删除该节点会遇到很复杂的情况。所以,在删除节点的时候,需要先对红黑树进行一些调整,使得删除节点对整个树的影响降到最低。

3.1 替换删除节点

首先根据 BST 删除节点的规则,使用当前节点左子树的最大值节点或者右子树的最小值节点代替其删除。这两个节点是其子树中数值上最贴近当前节点数值的节点)。这一点,只要懂了二叉查找树的删除操作就明白了,在这里不多说了。如下图所示:

图例:D 表示当前节点,P 表示父节点,B 表示兄弟节点,BR 表示兄弟节点的右子节点,BL 表示兄弟节点的左子节点

既然待删除节点是要被移走的,那肯定有一个节点要替换到它的位置上去。如何找到这个替换节点,这个过程和二叉查找树一模一样,要么在它的左子树下一直往右找到最大节点,要么在右子树下找到最小节点。

下面的描述过程采用的是右子树的最小值节点代替

当找到替换节点之后,现在需要考虑的情况就减少了,只可能会出现以下几种情况(因为需要满足红黑树特性):

  1. 无子节点,节点为红色

  2. 无子节点,节点为黑色

  3. 只有右子节点,右子节点为红色,节点本身为黑色

上面这三种情况,说的是新待删除节点。新待删除节点,就是即将被替换到待删除位置的节点。

因为 D 节点就是即将要替换到待删节点位置的节点,它同时又是右子树的最小值,既然是最小值了,它就不再可能拥有左子树了,所以只有可能有右子节点。另外,假如它有右节点且右节点的颜色是黑色,它自身颜色是红色,根本不成立。因为假如它自身为红色且又有黑孩子,那它必须要有两个黑孩子才满足红黑树性质,所以不满足。那有没有可能,它自身是黑色且右孩子也为黑色呢?也不可能!因为它左孩子已经为空了,说明它从自身出发到左子树的叶子的距离就是1,假如它右孩子也为黑色,那它从自身出发到右子树叶子的距离肯定大于等于2了,明显不可能。

所以总的来说只可能有下面三种情况:

  • 情况1:只需要直接删除节点就可以。删了一个红色新待删节点,不会影响红黑树性质。

  • 情况2:删除该 D 节点后,违反了红黑树特性5,需要调整(不考虑待删除节点为根节点的情况)

  • 情况3:用右子节点 R 占据待删除节点 D,再将其染成黑色即可,不违反红黑树特性。因为左边本来就是空了,其实右子树下即使有多少个黑色节点,也不会影响整体特性。

在这三种情况中,情况1和情况3比较简单,不需要多余的调整。情况2则需要后续的调整步骤使其满足红黑树特性。

3.2 调整红黑树

上述情况2的调整比较复杂。下面对各种情况进行讲解。

根据红黑树的特性5,待删除节点必然有兄弟节点。

为什么这么说呢?因为我们已经假设上面的 D 节点不为根了,那说明它肯定有父亲。首先它是没有孩子的,它下面直接就是叶子了,既然有父亲,不论它是父亲的左孩子或者右孩子,从父亲出发到它自身,黑色节点的个数为1。反证法:假如父亲只有它一个孩子,那说明父亲到另一边子树的叶子距离就为0,因为0个节点。这明显不符合,所以说明父亲肯定有两个孩子,那从而得知待删节点D必有兄弟。

下面根据其兄弟节点所在分支的不同,来分情况讨论。

以下是以关注待删节点为父节点的左子节点进行描述,如果遇到关注节点为父节点的右子节点的情况,则镜像处理。

**思路:**下面的任何调整只有一个目的,就是不断调整,直到调整到可以直接将 D 移除又不会影响红黑树特性的情况。但关键是调整过程中红黑树特性也不会发生改变。

图例:D 表示当前节点,P 表示父节点,B 表示兄弟节点,BR 表示兄弟节点的右子节点,BL 表示兄弟节点的左子节点

(1)兄弟节点为红色

将父节点染成红色,兄弟节点染成黑色,然后对父节点进行左旋操作。此时就转换为了下面的(4),之后按照(4)继续进行调整。

分析:这种情况,树的整体高度为2,变色左旋之后,整体高度还是保持在2。

(2)兄弟节点为黑色,远侄节点为红色

这种情况下,不需要考虑父节点的颜色。

  1. 将父节点 P 与兄弟节点 B 的颜色互换 ,这个过程父亲染黑

  2. 将兄弟节点的右子节点 BR 染成黑色

  3. 对父节点 P 进行左旋操作

可以看到,原本高度就是符合红黑树特性的,左右子树的高度都为1,因为黑色节点只有一个。经过这三步的调整后,直接删除节点 D 后仍然满足红黑树的特性,调整完成,跳出算法循环。

(3)兄弟节点为黑色,远侄节点为黑色,近侄节点为红色

这种情况下,兄弟节点的左节点染成黑色。兄弟节点染红。然后对兄弟节点做右旋。此时的状况就和(2)一样了。之后就通过(2)的调整方式进行调整。

(4)父节点为红色,兄弟节点为黑色,兄弟节点无子节点

这种情况下,将父节点P染成黑色,再将兄弟节点染成红色。经过这样的操作后,除去节点D后,以P为根节点的子树的黑节点深度并没有发生变化。调整完成。

怎么理解这个操作?

可以看左边,没调整前,P 的左右子树的黑色结点的数目都是1,是相同的,符合红黑树的性质:从任一节点到其叶子的所有简单路径都包含相同数目的黑色节点。然后再看右边,调整后,删掉 D 之后,P 结点的左右子树的黑色结点都是0个,仍然满足性质,所以调整完成。

(5)父节点为黑色,兄弟节点为黑色,兄弟节点无子节点

这种情况下,为了在删除节点 D 后使以 P 为根节点的子树能满足红黑树特性5,将兄弟节点 B 染成红色。但是这样操作后,以 P 为根节点的子树的黑色节点深度变小了。所以需要继续调整。

因为P节点子树的黑色深度发生了减少,可以把其当作待删除节点,那么此时就以 P 节点为关注节点进行进一步调整(继续向上调整)。这句话的意思我们再以 P 为起始点,继续根据情况进行平衡操作。就是把 P 当成 D,只是不要再删除 P 了。再看是这五种中的哪种情况,再进行对应的调整,这样一直向上,直到新的起始点为根节点或者关注节点不为黑色。

第五种情况,不会一直连续回溯的。假如能一直回溯,指针向上走之后,兄弟节点会一直都没有右孩子吗?不存在的。假如有这种情况,说明树的路径长度已经严重往左倾斜,肯定不可能。所以回溯这个情况只会回溯一次,不会连续回溯。第五个这种情况出现之后,下一次进入算法循环,肯定就是进入其他情况,直到遇到 break,跳出循环,终止整个算法过程。

3.3 检查根节点及删除节点

经过上述的调整后,此时基本满足了红黑树的特性。但是存在根节点变成红色的情况。所以需要将根节点染成黑色的操作。最后,执行删除操作,将待删除节点删掉。

当然从编程的角度,你也可以调整指针先把待删除节点移掉,然后再开始平衡调整过程。注意这里说的平衡调整,并不是 AVL 树的绝对平衡调整,而是满足红黑树特性的平衡调整。红黑树的平衡和 AVL 的平衡是有区别的。

Java实现

上面的操作篇幅比较长,假如没看明白,可以通过下面的代码继续看。

由于篇幅限制,源码请到原文链接查看 Java 实现

blog.youkuaiyun.com/weixin_42786274/article/details/86557922

总结

红黑树的删除操作是整个红黑树中最复杂的一部分,理解了这部分,红黑树就算基本拿下了。理解完一种数据结构,要能 get 到作者当初设计时的点,才算是一次积累。红黑树的删除操作,它非常地巧妙,整一个算法循环过程,它不会超过三次,调整过程基本都在子树内完成,指针不需要一直向上回溯,相比 AVL 树,AVL 树在删除节点时,指针有可能会一直回溯到根为止。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

数字盲水印嵌入和提取的实现基于小波变换DWT算法 数字盲水印是指在不知道原始图像的情况下,在其上嵌入水印并在后续的提取过程中能够恢复出原始水印的一种技术。本文介绍的数字盲水印嵌入和提取的实现方法基于小波变换DWT算法。具体来讲,DWT将信号或图像进行二次下采样和卷积滤波,使得高频分量的图像信息被集中在一个小区域内,方便进行嵌入和提取操作。其中 a 表示嵌入强度,而 watermark 则是用于嵌入的水印图像,这里我们嵌入的是一个全灰的图像。通过以上的代码,我们可以实现数字盲水印的嵌入和提取,并在一定程度上保护数字图片的版权安全。 阅读详情

相关推荐

RapidScada在windows下的安装(详细)

1.下载地址:RapidScada官网 2.版本说明 有Linux版本和Windows版本,看自己的需求下载,推荐下载最新稳定版本。 3.系统要求 4.安装前的准备(windows10) 首先打开Windows功能: 先关闭 Microsoft .NET Framework3.5的 Windows Communication Foundation 子组件。如下图: Microsoft .NET Framework配置按下图勾选: iis安装的功能: 5.安装 解压..

m0_51275803的博客 4264

Java之红黑树

1、简介 红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。 红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。 它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。 红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是

qq_41720578的博客 5602

使用 Cynthion 与 Packetry 进行 USB 抓包与协议分析

Cynthion 是 Great Scott Gadgets 推出的USB 流量分析与注入设备。它具备以下特点:通过 FPGA 实现高速 USB 流量捕获;能够同时作为 USB Host 和 Device,进行调试和测试;支持输出 pcap 文件,可直接用 Wireshark 分析;提供 Python API,方便与上层软件联动。简单来说,Cynthion 是一个USB 协议分析仪 + 注入工具。硬件层捕获:实时拦截 USB 总线上的数据包;软件层解析。

YIMUleizi的博客 1264

Java——红黑树

红黑树是一种平衡二叉搜索树,其节点由红、黑两种颜色组成。

m0_59408612的博客 1722

HarmonyOS NEXT 开发者预览版Beta招募应知测试

本次HarmonyOS NEXT 开发者预览版 Beta 招募活动为开发者预览版尝鲜升级,主要供开发者进行应用调测使用,除部分系统应用外,其他所有应用将被清除,因此在进行HarmonyOS NEXT 开发者预览版升级前,需进行数据备份。通过应知测试,并提交了参加HarmonyOS NEXT 开发者预览版招募 Beta 活动的报名信息,就会立刻审核通过并且收到新版本。手机在参加HarmonyOS NEXT 开发者预览版 Beta 招募活动前,需要对应机型升级到招募要求对应的基线版本,并预留内存空间。

长久公子的博客 8651

重带电粒子的能量歧离(energy straggling)

能量歧离,Bethe-Bloch

G751888629的博客 2298

Java 实现 红黑树(通俗易懂)

红黑树的概念和模拟实现

每篇博客都不是最终版,都会随着我的学习更新 3052

HPM6E00:PWM V2使用指南

HPM6E00:PWM V2使用指南

xikangsoon的博客 1734

红黑树理解以及Java实现

我对红黑树的理解 红黑树本身并不复杂,只是在插入删除的时候情况比较多,如果强行记忆的话会显得比较困难,而且容易忘记。所以以前对红黑树一直没有很好的掌握。恰好这次借着复习数据结构的机会,静下心来仔细的学习了一下红黑树,所以用这篇文章把我对红黑树的操作的理解记录下来,在理解的基础上记忆会容易得多,这样以后就不用重复学习啦! 1. 红黑树的定义 红黑树是一颗二叉查找树,且具有如下...

qq_41854763的博客 1万+

【OS】AUTOSAR OS系统调用产生Trap的过程详解

AUTOSAR OS系统调用产生Trap的过程详解

qq_36056498的博客 2440

YOLOv8结合GhostNet实现轻量化目标检测:模型设计与性能评测

GhostNet系列的核心是**“幽灵特征图(Ghost Feature Map)”** 概念:通过简单的线性变换(如深度卷积)生成“幽灵特征”,这些特征与原始特征融合后,能以极低的计算成本带来丰富的语义信息。为了突出GhostNet系列的必要性,设计消融实验:分别测试“仅主卷积”“仅幽灵卷积”“GhostNet(主卷积+幽灵卷积)”三种方案的性能,用数据证明“幽灵特征”的不可替代性。简单来说,引入GhostNet系列的YOLOv8,既能体现你的技术深度,又能让毕设的“落地性”大幅提升。

m0_71589036的博客 116

Java高阶数据结构之红黑树

本文是Java高阶数据结构的学习,剖析红黑树底层原理,红黑树的时间复杂度,红黑树的插入以及插入时的平衡调整。之后的学习内容将持续更新!!!

qq15035899256的博客 3727

Python APP反爬实战:Frida+Charles抓包,破解签名校验

Charles抓包定位参数 → jadx-gui反编译找函数 → Frida Hook拿密钥/规则 → Python还原签名算法;Frida的核心价值:Hook住APP的加密函数,拿到“输入(密钥/参数)+输出(签名)”,无需懂复杂的逆向底层;严格对齐APP的参数排序、拼接规则、加密算法,差一点都会验证失败。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1538

红黑树的理解与Java实现

前言 前段时间在研究JDK1.8的hashmap源码,看到put方法的插入环节,遇到了红黑树,不得不停止阅读源码的过程,因为还没掌握红黑树是无法完全读透hashmap源码的。红黑树作为一种数据结构,它被应用得非常多,可能很多人不认识它,但其实它已经在默默为我们的代码在发光发热。例如,你只要在Java中用到map,基本上就是在用红黑树(当元素个数到达八个时链表转红黑树)。 ps:在看这篇文章前,...

weixin_42786274的博客 2160

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

5张图带你彻底理解红黑树(含完整Java实现源码)

目前最清晰的红黑树图解。通过与2-3-4树对比来讲解红黑树的添加和删除

心中要有一片海的专栏 3636

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

java红黑树的理解与实现

红黑树,一个很牛x的数据结构,作为目前JDK的hashmap的底层,是一个兼顾了空间和时间的完美二叉查找树,在AVL的平衡性上做出了巨大改进。首先它的本质是一种特殊的AVL树,祖父辈是二叉排序树,就是那个左子节点必定小于等于它,右子节点必定大于它的树。 首先要了解红黑树就要从他的基本性质说起, 1.根节点必定为黑色 2.不能有两个连接的红色节点 3.节点颜色只能为红或者黑 4.任意节点到每个叶子节点途径的黑色节点数都是相同的 5.所有的子节点(NIL)必定为黑色 第一个性质,硬性规定,没有什么好说的 第二个

goldenzhouzhuo的博客 393

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

对于红黑树的理解和基于Java的实现

前面的文章中有几处都提到了红黑树,有小伙伴私信我说不是很理解红黑树的概念,今天刚好看到一篇大牛的文章,结合一些自己对红黑树的理解,如果下文中出现的字段有任何的问题都欢迎各位评论、私信我!祝大家小年快乐,阖家团圆!   前段时间在研究 JDK1.8 的 hashmap 源码,看到 put 方法的插入环节,遇到了红黑树,不得不停止阅读源码的过程,因为还没掌握红黑树是无法完全读透 hashmap 源...

程序员随笔 284
上一篇: 芋道 Spring Cloud Alibaba 注册中心 Nacos 入门
下一篇: 芋道 Spring Boot 数据库连接池入门
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值