红黑树的底层讲解

一、红黑树的介绍

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是红(red)或黑(black)。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因此是接近平衡的。(近似平衡)AVL树是严格平衡

红黑树有以下性质(规则):

1.每个结点不是红色就是黑色 

2.根结点是黑色的

3.如果一个结点是红色的,则它的两个孩子结点是黑色的。(一条路径中没有连续红色结点)

4.对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点(每条路径的黑色结点数量相等)

5.每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

以上四点,就能保证红黑树确保没有一条路径会比其他路径长出两倍(最短*2>=最长)第五点我们放在后面解释。

由于其底层也是二叉搜索树,结点的封装我们就不多说了(存放的还是pair类型,结点中包含其左右结点和父结点的指针)除此之外,我们还要用枚举记录颜色,基本就是如图:

颜色给什么我们一会再说。

二、红黑树的基本功能实现

1.插入数据

此时会面临一个选择, 是插入红色还是黑色,这要看插入后对其他结点的影响大不大,对于红色,我们只要保证路径无连续红色即可,即使插入后有连续红色也只是在这一条路径上更改,但黑色就不一样了,需要保证每条路径的黑结点数量相等,一旦一条路插入黑色,所有的其他路径都要修改,代价和红色比还是很大的。所以,我们先讨论插入红色结点的情况

以下面这棵树(或子树)为例

其中,p代表parent  g代表grandfather  u 代表uncle

前提条件:abcde均为空,cur为新增

我们一开始先不考虑用旋转来解决问题,毕竟旋转的操作影响比较大,且目的是实现完全平衡,但我们的红黑树的目的是实现近似平衡即可,因此尽量减少工作量。

其中,以上有几个结点的颜色已经是确定的:cur红色结点,parent一定也是红色结点(因为如果parent是黑色结点那么我们cur的插入操作就符合红黑树的规则,不需要再调整了,我们这里所有情况都是当cur插入后树不符合红黑树的规则下),grandfather一定是黑色(parent已经是红了,一条路不可能出现连续红色)。因此,唯一可变性就在这个uncle结点。

情况一:当uncle存在且是红结点,为了保证规则,首先需要把parent转变为黑,同时把uncle变红,而且要把grandfather变红(因为每个路径的黑结点数量一定是相同的,经过上面的操作后,两条路径均新增一个黑结点,为了保持和别的路径相等,需要把grandfather变红保持相等,但如果grandfather 本身是根就没必要)然后再向上调整,把grandfather当成cur调整。

在情况一的前提条件下,ab为红,cde为只有一个黑色结点的子树,那么其情况就有上百种,我们在后续也就不过多分析了。

情况二之一:当uncle不存在(abcde均为空,cur为新增且为parent的左) 如下图左边

此时如果我们像情况一的处理方式貌似无法解决问题,破坏了黑色数量的平衡,因此我们只能旋转处理(上图右为旋转后的结果)

情况二之二:当uncle不存在(abcde均为空,cur为新增且为parent的右) 

此时我们通过单旋就无法满足要求了,需要进行双旋,先以parent为中心进行一次做单旋,此时情况就变成了情况二之一,再加个以g为中心的右旋即可满足。

情况三:uncle存在且为黑色

处理方法:旋转(以g为中心的右单旋),让g的位置变成p,p的左不变,右变为g,g右不变,左变成c,然后p变黑,g变红

其实,无论uncle是空还是为黑色,其操作原理完全相同,因此我们当只需要单旋成为情况二,双旋为情况三

我们用代码分析一下以上的所有情况,还是和前面的类似,需要写在插入函数中,而且,其中左旋和右旋的函数在上节的AVL树已经讲解完原理,所以代码中对这部分就不讲解了(这边附上AVL树的链接https://blog.csdn.net/czt230610/article/details/135952308?fromshare=blogdetail&sharetype=blogdetail&sharerId=135952308&sharerefer=PC&sharesource=czt230610&sharefrom=from_link)

//....上面是插入函数while(parent&&parent->_col==RED)//必须为红色,否则插入后无需修改{Node*grandfather =parent->_parent;if(parent==grandfather->_left)  //大前提,研究的都是左边一边高{                              //当右边高的时候代码原理相同Node*uncle=grandfather->right;if(uncle&&uncle->_col==RED) //情况一{parent->_col=BLACK;uncle->_col=BlACK;grandfather->_col=RED;cur=grandfather;parent=cur->_parent;}else //uncle不存在或者为黑色   情况二{if(cur==parent->_left) //一边高,单旋即可{rotater(grandfather);//改色parent->_col=BLACK;grandfather->_col=RED;}else//不是一边高,双旋 情况三{rotatel(parent);rotater(grandfather);//改色cur->_col=BLACK;grandfather->_col=RED;}break;}} else//parent在右uncle在左{Node* uncle = grandfather->_left;// 叔叔存在且为红,-》变色即可if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;// 继续往上处理cur = grandfather;parent = cur->_parent;}else // 叔叔不存在,或者存在且为黑{// 情况二:叔叔不存在或者存在且为黑// 旋转+变色//      g//   u     p//            cif (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//		g//   u     p//      cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}				}_root->_col = BLACK;//无论情况一之后是否需要向上调整都把根变黑//避免了多情况分析
}

正文结束 

麻烦留下你宝贵的点赞与收藏,这对我的动力真的很大!

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

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

相关文章

linux环境下的程序设计与git操作

目录 前言: 进度条小程序: 先介绍几个背景知识 代码实现 Git操作 总结 其他指令 前言: 本文将重点介绍1. linux下的程序设计,并使用linux下的几个函数接口。实现一个简单的小程序 2.本着开源精神,进行git操作。…

Vue详细入门(语法【三】)

今天滴的学习目标!!! Vue组件是什么?组件的特性和优势Vue3计算属性Vue3监听属性 在前面Vue详细入门(语法【一】——【二】)当中我们学习了Vue有哪些指令,它的核心语法有哪些?今天我们…

(AtCoder Beginner Contest 375) 题解(下)

一、题解 第 E 题 3 Team Division 一眼看像背包,观察数据范围,合法的总能力值 ≤ 500 \le 500 ≤500,那么我们可以设计一个背包DP: int dp[110][510][510]; //dp[i][j][k] 表示前 i 个人,分给第一组的能力值是 j&…

微服务架构 --- 使用Seata处理分布式事务

目录 一.Seata 是什么? 1.Seata的核心架构: 2. Seata的分布式事务处理流程: 二.Seata的基本使用: 1.环境准备: 2.引入依赖: 3.加入配置来使用Seata: (1)首先在nacos上添加一…

免费版视频压缩软件:让视频处理更便捷

现在不少人已经习惯通过视频来记录生活、传播信息和进行娱乐的重要方式。但是由于设备大家现在录制的文件都会比较大,这时候就比较需要一些缩小视频的工具了。今天我们一起来探讨视频压缩软件免费版来为我们带来的生动世界。 1.Foxit视频压缩大师 链接直达&#x…

ESP32移植Openharmony外设篇(1)MQ-2烟雾传感器

外设篇 实验箱介绍 旗舰版实验箱由2部分组成:鸿蒙外设模块(支持同时8个工作)、鸿蒙平板。 其中,鸿蒙平板默认采用RK3566方案。 OpenHarmony外设模块采用底板传感器拓展板方式,底板默认采用ESP32方案,也…

青少年编程能力等级测评CPA C++一级试卷(1)

青少年编程能力等级测评CPA C一级试卷(1) 一、单项选择题(共20题,每题3.5分,共70分) CP1_1_1.在C中,下列变量名正确的是( )。 A.$123 B&#…

Redis 的安装与部署(图文)

前言 Redis 暂不支持Windows 系统,官网上只能下载Linux 环境的安装包。但是启用WSL2 就可以在Windows 上运行Linux 二进制文件。[要使此方法工作,需要运行Windows 10 2004版及更高版本或Windows 11]。本文在CentOS Linux 系统上安装最新版Redis&#xf…

【C++】unordered_set、unordered_map超详细封装过程,处理底层细节

🚀个人主页:小羊 🚀所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言1、数据泛型2、迭代器2.1 重载2.2 begin、end2.3 const迭代器2.4 unordered_map中[]重载 3、特殊类型 总结 前…

如何设计开发RTSP直播播放器?

技术背景 我们在对接RTSP直播播放器相关技术诉求的时候,好多开发者,除了选用成熟的RTSP播放器外,还想知其然知其所以然,对RTSP播放器的整体开发有个基础的了解,方便方案之作和技术延伸。本文抛砖引玉,做个…

Unity 实战案例全解析 实现时间停止效果+世界变灰

画面里运动的那个小玩意这么写 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Partol : MonoBehaviour {public Transform pos1;public Transform pos2;public float speed;private Transform target;void Start() {target p…

前端开发攻略---取消已经发出但是还未响应的网络请求

目录 注意&#xff1a; 1、Axios实现 2、Fetch实现 3、XHR实现 注意&#xff1a; 当请求被取消时&#xff0c;只会本地停止处理此次请求&#xff0c;服务器仍然可能已经接收到了并处理了该请求。开发时应当及时和后端进行友好沟通。 1、Axios实现 <!DOCTYPE html> &…

性能测试工具JMeter

本次使用的博客系统的url&#xff1a; http://8.137.19.140:9090/blog_edit.html 1. JMeter介绍 环境要求&#xff1a;要求java&#xff0c;jdk版本大于8&#xff1b; Apache JMeter 是 Apache 组织基于 Java 开发的压⼒测试⼯具&#xff0c;⽤于对软件做性能测试&#xff1b…

带新手用一套坦克大战搞定Java核心编程

有不少在校大学生朋友私信笔者&#xff0c;觉得现在的Java教程学的比较枯燥&#xff0c;有没有能学到基础知识同时还有做项目感觉的教程。因为笔者最早接触Java时学的是马士兵老师、韩顺平老师这样的大佬当时出的教程&#xff0c;尤其印象深刻的是二位大佬的坦克大战项目&#…

基于DSP+ARM+FPGA的电能质量分析仪的软件设计

软件设计是电能质量设备的核心内容&#xff0c;上述章节详细介绍了电能质量参数的 算法&#xff0c;并且通过仿真实验进行了验证&#xff0c;本章将结合现代电能质量监测设备需求实 现算法在实际电网中应用。根据设计的电能质量分析仪的需求分析&#xff0c;进行总体的 软件…

Java筑基之路:运算符深入(下)

&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d; &#x1f947;博主昵称&#xff1a;小菜元 &#x1f35f;博客主页…

计算机网络:数据链路层 —— 共享式以太网

文章目录 共享式以太网CSMA/CD 协议CSMA/CD 协议 的基本原理 共享式以太网的争用期共享式以太网的最小帧长共享式以太网的最大帧长共享式以太网的退避算法截断二进制指数退避算法 共享二进制以太网的信道利用率使用集线器的共享式以太网10BASE-T 共享式以太网 共享式以太网是当…

51单片机数码管循环显示0~f

原理图&#xff1a; #include <reg52.h>sbit dulaP2^6;//段选信号 sbit welaP2^7;//位选信号unsigned char num;//数码管显示的数字0~funsigned char code table[]{ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};//定义数码管显…

yakit使用教程(四,信息收集)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言&#xff1a;yakit下载安装教程。 一&#xff0c;基础爬虫。 在新建项目或新建临时项目后&#xff0c;点击安全工具&#xff0c;点击基础爬虫。 此工具并不是为了爬取网站上的一…

navicat下载教程(包会的)

目录 一、下载navicat安装包 步骤1---试用版本 步骤2---下载windws系统的navicat​编辑 步骤3---查看安装包 二、安装navicat 三、唤醒navicat 四、成功唤醒navicat 官网地址&#xff1a;Navicat | 下载 Navicat Premium 14 天免费 Windows、macOS 和 Linux 的试用版 …