数据结构和算法之树形结构(4)

文章出处:数据结构和算法之树形结构(4)     

关注码农爱刷题,看更多技术文章!!!

六、红黑树(接前篇)

       红黑树是为了弥补AVL树在大规模频繁增删节点场景下性能不理想而设计出来的一种平衡二叉查找树。红黑树不是一种严格的平衡树,它通过牺牲一定的平衡性来降低增删节点时自平衡旋转的执行次数,以此来满足大规模频繁增删节点场景下的性能需求。

      红黑树规范

      在了解红黑树是怎样通过它的自平衡机制降低旋转的执行次数从而在大规模频繁增删节点场景下获得更好性能之前,我们们先了解红黑树的相关概念和规范,红黑红黑,顾名思义,红黑树是一棵有颜色的树,非黑即红,这正是其与AVL树不同的特点:它在每个节点上增加一个存储位表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍(即最长路径也不会超出最短路径的两倍,因此红黑树的平衡性要求相对宽松,没有AVL树那样严格),从而使二叉查找树达到一种相对平衡的状态即节点高度的相对平衡。具体关于红黑树的规范和特点总结如下表:

图片

      那红黑树的上述规范应该怎么理解呢?红黑树又是怎样保证二叉查找树的相对平衡的呢?其实,正是以上几条规范,特别是第4条和第5条保证了二叉查找树的相对平衡。其中第4条隐藏的含义就是,同一条路径下不能有连续的两个红色节点,而第5条规范的意思是不论是最短路径还是最长路径黑色节点数必须相同;正是这两条的限制,使最短路径和最长路径的相差不会超出两倍。这么说可能不直观,我们举例说明:假设有一起始节点为黑色,其最短路径有两个黑色子孙节点,其长度为3,对于其最长路径和最短路径差距可以有下表的推断:

图片

图片

     从上图1-1及对应表的推断内容,不难看出正是第4、5条规范约束了最长路径的长度(至于图1-1右方红节点14、16和18下方补了黑节点也是为了让所有路径都满足规范5),从而保证了二叉查找树高度的相对平衡,当然其他的规范也起了作用,例如规范1规定每个节点非黑即红。如果觉得这是个例,我们可以再换一个案例:把起始节点换成红色,则对于其最长路径和其最短路径可以有下表的推断:

图片

图片

     从图1-2和上表可以看到,最长路径已经不到最短路径的两倍,换句话说,相比案例一,节点的平衡性更高。即使你在案例一基础上对最短路径增加新的黑色节点(增加红色节点,对最长路径的长度增加没有变化),那最长路径的最多也就是增加相同数目的红色节点和黑色节点,总节点数依然在两倍以内。简单的说,规范5约定了每条路径只能有相同数目的黑节点,当黑节点数不变时,则要增加某条路径的长度或高度,则只能添加红节点,而规范4约定了同一路径红节点不能相邻连接,那在某条路径上可以增加的红节点数最多也不会超过黑节点的数目,那么最长路径自然最多只能是最短路径的两倍。所以以上两个案例以前能充分地说明了,正是红黑树前述规范保证了其二叉查找树高度的相对平衡。

       我们再仔细看看规范3和规范5,都提到了叶子节点:

规范3:叶子节点都是黑色(此处指nil节点或null节点)规范5:任意节点到达其每个叶子节点的简单路径上,黑色节点数目相同。

      其中,黑色节点数目相同这个黑色节点数就包括了必须是黑色的叶子节点。那为空的黑色叶子节点到底有什么作用呢? 在前文针对图1-1和图1-2中的阐述中,没有叶子节点,规范不一样实现了对二叉查找树相对平衡的保证?我们先来看两幅图:

图片

图片

     上图1-3是没有叶子节点的情况,从节点20到到末端节点只有两条路径,图1-4是有叶子节点的情况,从节点20到各叶子节点则有六条路径;如果没有叶子节点,我们肯定认为图1-3是有效的红黑树,满足了规范4和5的要求,因为每条路径上只有2个黑色节点,也是相对平衡的,不用再进行平衡调整;而图1-4把叶子节点画出来之后,我们可以看到节点20-25-null这条路径上只有两个黑色节点(包括叶子节点),而其他路径上是则为3个黑色节点,所以还需要进一步进行平衡调整,即要对节点24进行右旋,处理成下图1-5的结果:

图片

      这就是有叶子节点和没有叶子节点的区别,有和没有叶子节点对后续自平衡的处理结果会不同;这里没有对错,只是有叶子节点,红黑树自平衡的处理和应用会更加方便,大家在后续实践中会明白,下面是大模型通义千问的回复:

    在一些红黑树的实现中,会使用一种特殊的“叶子节点”概念来简化插入和删除操作。这些通常被称为“哨兵”节点,它们总是被设定为黑色,并且通常指向一个空值(nil 或 null)。这些哨兵节点可以被视为红黑树的外部节点,而真正的数据存储在内部节点中。这样的设计可以使得边界情况处理更加简单,因为在插入或删除时,不需要频繁地调整指针来处理原本的空指针位置。使用这些“哨兵”或“伪叶子节点”的好处包括:

1.插入或删除操作后更容易维护红黑树的性质。2.可以避免在边界情况下处理空指针,从而简化了代码逻辑。3.在进行旋转等平衡调整操作时,可以更方便地处理边界情况。

     需要注意的是,并不是所有的红黑树实现都会采用这种带哨兵节点的方法;有些实现会直接处理空指针,而不是使用哨兵节点。

     总之,叶子节点的引进是为了后续调整平衡更加方便。同样,规范2约定根节点必须是黑色,也是为了简化代码实现、保持树的平衡,以避免红色节点的连续出现,以及考虑到红黑树与2-3树的关系。 

      自平衡机制

      接下来,我们介绍红黑树的自平衡机制,讲述红黑树是怎样通过它的自平衡机制降低旋转的执行次数的。红黑树自平衡机制用来调整平衡的方法只有三个,简而言之:变色、左旋和右旋。我们先简单介绍这三种方法,再结合增删节点场景来讲,因为通常只有增删节点后才需要调整平衡。三种方法总结如下表:

图片

     以上是三种方法的基本定义和发生时机,但具体需要结合增删节点场景来决定何时用变色,何时用左旋和右旋进行平衡调整,因为只有增删节点时,才会让红黑树的相对平衡遭到破坏从而需要调整。

     这里说明一下,我们后续讲到的分情况的场景,都是指新增之前或被删除之前的场景,而且在新增或删除发生之前,场景下的红黑树应该是相对平衡且没有违反红黑树的所有规范。

     插入场景的自平衡处理

     对于新增的节点来说,其颜色必须是红色,这也是约定成俗的规范,因为新增节点为黑色会违反规范5,会改变某些路径上黑色节点的数目,从而破坏平衡性,同时这样约定,也是为了方便后续的调整处理。

     通常对于新增的节点,在其被新增之前,其父节点只有黑色和红色两种。其中对于黑父,新增节点时不用作任何处理,因为此时新增红色节点不会影响所有路径上黑色节点的数目,也不会违反任何规范。而对于红父,新增红色节点会出现红红相连,违反规范4需要调整;一般分红父无叔节点和红父有叔节点两种情况。

      红父无叔节点

     对于这种情况,一般处理方法包括两部分:变色和旋转,变色一般是把其父节点和祖父节点颜色互换,父节点变黑,祖父节点变红;至于是左旋还是右旋和旋转几次,取决于新增节点和父节点的位置;变色和旋转没有顺序先后,先变色先旋转都可以。

1. 红父为左节点,新增节点也为左节点

   

图片

     上图1-6新增节点6N和父节点15P红红相连违反红黑树规范4,处理逻辑是:先变色,父节点15P变为黑色,祖父节点20G变为红色;后右旋父节点15P,使之替代祖父节点位置,祖父节点20G成为父节点15P的右节点

      处理后,满足红黑树各规范,各路径上黑色节点数相同无红红相连。

2. 红父为左节点,新增节点为右节点

图片

     上图1-7新增节点18N和父节点15P红红相连违反红黑树规范4,处理逻辑是:先左旋新节点18N,替代父节点15P位置,使父节点15P位置成为其左节点;此时还原成图1-6初始状态,则按图1-6的处理逻辑做后续调整

      处理后,满足红黑树各规范,各路径上黑色节点数相同无红红相连。

3. 红父为右节点,新增节点也为右节点

图片

    上图1-8新增节点26N和父节点25P红红相连违反红黑树规范4,处理逻辑是:先变色,父节点25P变为黑色,祖父节点20G变为红色;后左旋父节点25P,使之替代祖父节点位置,祖父节点20G成为父节点25P的左节点

      至此,处理后子树满足红黑树各规范,各路径上黑色节点数相同无红红相连。

 4. 红父为右节点,新增节点也为左节点

图片

    上图1-9新增节点23N和父节点25P红红相连违反红黑树规范4,处理逻辑是:先右旋新节点23N,替代父节点25P位置,使父节点25P位置成为其右节点;此时还原成图1-8初始状态,则按图1-8的处理逻辑做后续调整

      处理后,满足红黑树各规范,各路径上黑色节点数相同无红红相连。以上是新增节点红父无叔节点的情况。

     红父有叔节点

     对于这种情况,新增节点的叔节点只能是红色,不会存在黑色叔节点的场景。一般处理逻辑包括两部分:第一部分是对以新增节点为基础往上的三代进行变色;第二部分是对新增节点的祖父节点往上三代进行变色和旋转处理并递归,我们暂称之为祖父节点们的递归处理;这里是有顺序的,处理完第一部分,才能确定是否要进行第二部分处理,如果祖父节点和其父节点没有出现红红相连的情况,就无须处理,否则要继续往上处理甚至递归。

红父红叔情况下第一部分变色逻辑处理

图片

    上图1-10新增节点23N和父节点20P红红相连违反红黑树规范4,处理逻辑是:只用变色处理,把父节点20P和叔节点28U变成黑色,再把祖父节点25G变成红色

     对于第一部分的处理,不用考虑父节点和新增节点的位置,因为只是颜色的变换,没有涉及旋转位置的移动;变色后,第一部分的处理结束。此后,要看祖父节点25G和它的父节点是否会出现红红相连的情况,如果出现,则要进行第二部分的祖父节点们的递归处理。而往上递归处理的场景需要考虑多种场景,这里就会出现红父黑叔的场景,基于不同场景酌情处理。祖父节点的递归处理的场景如下,其实和新增节点大同小异,只是祖父节点的红父黑叔场景要等同新增节点的红父无叔节点场景处理。

1. 红父红叔,等同新增节点图1-10的处理逻辑

     处理逻辑同图1-10是:只用变色处理,把父节点和叔节点变成黑色,再把祖父节点变成红色

2. 红父黑叔,红父为左节点,目标节点为左节点,处理逻辑同图1-63. 红父黑叔,红父为左节点,目标节点为右节点,处理逻辑同图1-74. 红父黑叔,红父为右节点,目标节点为右节点,处理逻辑同图1-85. 红父黑叔,红父为右节点,目标节点为左节点,处理逻辑同图1-9

     所以不论是新增节点,还是对于要被递归处理的祖父节点们,其实归纳起来就五种场景和对应的五种处理逻辑(如果把叶子节点画上,新增节点的红父无叔场景就等同红父黑叔场景,这也正说明了叶子节点的作用,简化了红黑树场景分析),当然实际处理时,可能是以上五种场景和处理逻辑的嵌套和组合。从上述处理逻辑,我们可以看到,红黑树在处理新节点插入时,在黑父和红父红叔的两种场景下,完全不用旋转,要么不用处理要么就通过变色处理;其他场景,也可以通过旋转和变色组合来降低旋转次数。

     考虑这篇文章的篇幅和红黑树删除场景的复杂性,关于红黑树的删除的自平衡处理和各种场景,决定单独放到一章去讲解。烦请关注!

码农爱刷题

为计算机编程爱好者和从业人士提供技术总结和分享 !为前行者蓄力,为后来者探路!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读】Diffusion Policy: Visuomotor Policy Learning via Action Diffusion

Abstract 本文介绍了扩散策略,这是一种通过将机器人的视觉运动policy表示为条件去噪扩散过程来生成机器人行为的新方法。我们对来自 4 个不同的机器人操作基准的 15 个不同任务的扩散策略进行了基准测试,发现它始终优于现有的 state-of-the-art 机器人学…

word批量裁剪图片,并调整图片大小,不锁定纵横比

在word中有若干图片待处理,裁剪出指定内容,调整成指定大小。如下是待处理的图片: 这时,选择视图,选择宏,查看宏 选择创建宏 添加cut_picture代码如下,其中上、下、左、右裁剪的橡塑尺寸根据自己…

C#入门教程

目录 1.if分支语句 2.面向对象 3.static简单说明 1.if分支语句 我们的这个C#里面的if语句以及这个if-else语句和C语言里面没有区别,就是打这个输出上面的方式不一样,c#里面使用的是这个console.writeline这个指令,其他的这个判断逻辑都是一…

【优选算法】(第四篇)

目录 三数之和(medium) 题目解析 讲解算法原理 编写代码 四数之和(medium) 题目解析 讲解算法原理 编写代码 三数之和(medium) 题目解析 1.题目链接:. - 力扣(LeetCode&…

鸿蒙开发(NEXT/API 12)【基础功能(使用剪贴板进行复制粘贴)】剪贴板服务

场景介绍 [剪贴板]为开发者提供数据的复制粘贴能力。 当需要使用复制粘贴等功能时&#xff0c;例如&#xff1a;复制文字内容到备忘录中粘贴&#xff0c;复制图库照片到文件管理粘贴&#xff0c;就可以通过剪贴板来完成。 约束限制 剪贴板内容大小<128MB。为保证剪贴板数…

【Java】Java中String、StringBuilder、StringJoiner详解

目录 引言 一、String 1.1 String的定义 1.1.1 直接赋值 1.1.2 new关键字创建 1.2 常用方法 1.3 字符串的不可变性 1.4 字符串内存的存储原理 二、StringBuilder 2.1 常用方法 2.2 动态扩容策略 2.3 使用场景 三、StringJoiner 3.1 构造方法 3.2 常用方法 3.3…

【图像处理】多幅不同焦距的同一个物体的平面图象,合成一幅具有立体效果的单幅图像原理(二)

实现多幅不同焦距图像合成一幅具有立体效果的图像可以使用以下算法和开源库&#xff1a; 实现算法 图像对齐 使用特征点匹配&#xff08;如 SIFT、SURF 或 ORB&#xff09;来对齐图像。利用 RANSAC 算法剔除离群点&#xff0c;估计变换矩阵。 深度图生成 基于图像的焦距和视角…

信息安全工程师(19)HASH函数与数字签名

一、Hash函数 1、定义 Hash函数&#xff0c;又称散列函数或哈希函数&#xff0c;是一种将任意长度的输入&#xff08;称为预映射或消息&#xff09;通过散列算法变换成固定长度输出&#xff08;称为散列值或哈希值&#xff09;的函数。这种转换是单向的&#xff0c;即不能从哈…

使用python爬取豆瓣网站?如何简单的爬取豆瓣网站?

1.对python爬虫的看法 首先说说我对python的看法&#xff0c;我的专业是大数据&#xff0c;我从事的工作是java开发&#xff0c;但是在工作之余&#xff0c;我对python又很感兴趣&#xff0c;因为我觉得python是一门很好的语言&#xff0c;第一&#xff1a;它可以用来爬取数据…

ROS与无人驾驶学习笔记(一)——ROS基本操作

文章目录 ※ 安装ubuntu 下载 创建虚拟机 安装系统 安装vmware tool 更新源 安装常用软件 ※ 安装ROS 设置软件更新 使用清华源安装 ros测试 认识ROS ROS特点 ROS系统实现 ROS安装 工作需要&#xff0c;转行做码农了。。。 大概是无人驾驶相关的&#xff0c;啥都不会。。。 看成…

arthas简单应用

背景说明 项目上某个接口响应时间过长&#xff0c;需要查看方法耗时情况进行优化 安装配置 访问下载页进行下载&#xff1a;下载 | arthas 调整文件位置进行解压缩 - 查看arthas帮助命令&#xff08;非必须&#xff0c;官网文档更详细&#xff09; C:\tools\arthas\4.0.1\b…

IvorySQL 3.4 来了

9 月 26 日&#xff0c;IvorySQL 3.4 发版。本文将带大家快速了解新版本特性。 IvorySQL 3.4 发版说明 IvorySQL 3.4 基于 PostgreSQL 16.4&#xff0c;修复了多个问题&#xff0c;并增强多项功能。 PostgreSQL 16.4 的变更 在未经授权时防止 pg_dump 执行&#xff0c;并引入一…

MMD模型一键完美导入UE5-VRM4U插件方案(一)

1、下载pmx模型 1、去模之屋官网下载MMD模型,模之屋 2、下载完成得到pmx和Texture文件 2、下载并启用VRM4U插件 1、下载VRM4U插件, VRM4U,点击Latest下载对应引擎版本 2、将插件放到Plugins目录,然后

Git GUI操作流程

1&#xff0c;点击运行 Gt GUI 2&#xff0c;界面如下 3&#xff0c;点击Creat new Repository或者在菜单栏点击Repository--new 4,点击Browse选择目录&#xff0c;点击create&#xff0c;创建本地git仓库 5&#xff0c;对应盘里生成一个.git文件&#xff0c;用于版本管理 6&am…

随记——机器学习

前言 本来有个500块钱的单子&#xff0c;用机器学习做一个不知道什么鸟的识别&#xff0c;正好有数据集&#xff0c;跑个小项目&#xff0c;过一下机器学习图像识别的流程&#xff0c;用很短的时间记录下来..... 一、数据预处理 将数据集分为训练集和测试集&#xff0c;直接…

基于SpringBoot校园失物招领系统设计与实现

文未可获取一份本项目的java源码和数据库参考。 本课题的作用、意义&#xff0c;在国内外的研究现状和发展趋势&#xff0c;尚待研究的问题 作用&#xff1a;本课题的目的是使失物招领信息管理清晰化&#xff0c;透明化&#xff0c;便于操作&#xff0c;易于管理。通过功能模…

vue3 选择字体的颜色,使用vue3-colorpicker来选择颜色

1、有的时候我们会用到颜色的选择器&#xff0c;像element-plus提供了&#xff0c;但是ant-design-vue并没有&#xff1a; 这个暂时没有看到&#xff1a; 但是Ant Design 5的版本有&#xff0c;应该不是vue的。 2、使用第三方提供的vue3-colorpicker&#xff1a;storybook/cli…

【Gitee自动化测试3】Git的本地使用,和在Gitee上使用

一. 创建版本库 存放项目&#xff0c;项目的删除更改&#xff0c;版本库都能够监控。 创建一个文件夹&#xff08;不要包含中文路径&#xff09;&#xff0c;右键选择Git Bash Here&#xff08;打开Git终端&#xff09; 输入git init 对文件夹进行版本库的初始化&#xff0c;…

【CSS】背景

background-color 颜色background-image 图像background-size 缩放background-repeat 平铺background-position 定位background-clip 裁剪区域background-origin 开始区域background-attachment 滚动方式 background-color 颜色 <style>div{width: 200px;height: 100px;…

LeetCode - 850 矩形面积 II

题目来源 850. 矩形面积 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个轴对齐的二维数组 rectangles 。 对于 rectangle[i] [x1, y1, x2, y2]&#xff0c;其中&#xff08;x1&#xff0c;y1&#xff09;是矩形 i 左下角的坐标&#xff0c; (xi1, yi1) 是该…