【数据结构】红黑树

导语

之前平衡二叉树讲解中,可以了解到AVL在插入或删除频繁的场景,需要消耗大量的时间来调整,使树重新满足平衡条件。红黑树就此作出优化,在查询速率和平衡调整中寻找平衡,放宽了树的平衡条件,从而可以用于 增加删除 频繁的场景。


一、红黑树的基本概念

1、红黑树的定义

红黑树(Red Black Tree)是一颗自平衡(self-balancing)的二叉排序树(BST)

【注意,这里的自平衡和平衡二叉树AVL的高度平衡不同

在红黑树中,节点被标记为红色和黑色两种颜色。

树上的每一个结点都遵循下面的规则:

  • 特性1:节点非黑即红

  • 特性2:根节点一定是黑色

  • 特性3:叶子节点(NULL)一定是黑色

  • 特性4:每个红色节点的两个子节点都为黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

  • 特性5:从任一节点到其每个叶子的所有路径,都包含相同数目的黑色节点。【平衡特征】

如果一个结点没有子结点或父结点,则该结点相应属性值为NULL。

这些NULL被视为指向二叉搜索树的叶结点(外部结点)的指针,而把带关键字的结点视为树的内部结点。

为了便于处理红黑树代码中的边界条件,使用一个NULL来代表所有的NIL:所有的叶结点和根结点的父结点。

 红黑树并不一定是一棵AVL平衡二叉搜索树。

 如上图,这个树是一棵红黑树,但是不是一棵AVL平衡二叉树。

红黑树的特性5,从任一节点到其每个叶子的所有路径,都包含相同数目的黑色节点, 说明:

红黑树的 左子树和右子树的黑节点的层数是相等的

红黑树的平衡条件,不是以整体的高度来约束的,而是以黑色节点的 高度 来约束的

所以称红黑树这种平衡为黑色完美平衡

 结点的黑高(bh:从某结点出发(不含该结点)到达任一空叶结点的路径上黑结点总数。

二、红黑树的存储结构

对于红黑树,首先是二叉搜索树,所以会有 左右孩子指针 和 数据域,然后特殊之处是每个结点都有颜色,所以需要加一个 颜色标记(Red or Black)

enum Color {Red,Black
};struct RBNode {struct RBNode* parent;struct RBNode* left;struct RBNode* right;int data;Color color;RBNode(int val) :parent(nullptr), left(nullptr), right(nullptr), data(val),color(Red) {}
};

【为什么创建结点时默认结点颜色为红色?】

红色在父结点(如果存在)为黑色结点时,红黑树的黑色平衡没被破坏,不需要做自平衡操作。但如果插入结点是黑色,那么插入位置所在的子树黑色结点总是多1,必须做自平衡。

三、自平衡操作

1、左旋

以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。

 2、右旋

以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。

3、变色

 结点的颜色由红变黑或由黑变红。

四、红黑树的基本操作

1、查找

对于要查找的数据 data,从根结点出发,每次选择左子树或者右子树进行查找,总共四种情况依次进行判断:

1)若为空树,直接返回 false;

2) data 小于 树根结点的数据域,说明 data 对应的结点不在根结点,也不在右子树上,则递归返回左子树的 查找 结果;

3) data 大于 树根结点的数据域,说明 data 对应的结点不在根结点,也不在左子树上,则递归返回右子树的 查找 结果;

4) data 等于 树根结点的数据域,则直接返回 true ;

bool RBTreeFind(RBNode* T, int data) {if (T == nullptr) {return false;                        // 空树}if (data < T->val) {return RBTreeFind(T->left, data);       // data<val,递归查找左子树}else if (data > T->val) {    return RBTreeFind(T->right, data);      //  data>val,递归查找右子树}return true;                             //  data=val
}

2、插入

(1)原理分析

和AVL平衡二叉树类似,红黑树的插入首先需要找到合适的插入位置,特殊的的是插入过程需要为新元素染色且需要重新平衡。

对于要插入的数据 data ,从根结点出发,分情况依次判断:

【情景1】:红黑树为空树。 【处理】把插入结点作为根结点,并把结点由红色变为黑色。

【情景2】:插入结点数据data已存在。 【处理】无须执行插入,直接返回。(若是key-value结构,需要更新当前结点的值为插入结点的值)

【情景3】:插入结点的父结点为黑色结点。 【处理】:直接插入。

【情景4】:插入结点的父结点为红色结点。

【情景4-1】:叔叔结点存在并且为红结点。

【处理】:① 将P(父亲结点)和U(叔叔结点)设置为黑色

                  ② 将G(祖父结点)设置为红色

                  ③ 将G 设置为当前插入结点

RBTree插入情景4-1示例图

【情景4-2】:叔叔结点不存在或者为黑结点,并且插入结点的父亲结点是祖父结点的左孩子结点。 

【情景4-2-1】插入结点是其父结点的左子结点

【处理】:① 将 P 设置为黑色

                  ② 将 G 设置为红色

                  ③ 以 P 为支点,对 G 进行右旋

RBTree插入情景4-2-1示例图

 【情景4-2-2】插入结点是其父结点的右子结点

 【 处理】:① 对 P 进行左旋

                    ② 把 P 设置为插入结点

                    ③ 进行情景4-2-1处理

RBTree插入情景4-2-2示例图

【情景4-3】:叔叔结点不存在或者为黑结点,并且插入结点的父亲结点是祖父结点的右孩子结点。 

【情景4-3-1】插入结点是其父结点的右子结点

【处理】:① 将 P 设置为黑色

                  ② 将 G 设置为红色

                  ③ 以 P为支点,对 G 进行左旋

RBTree插入情景4-3-1示例图

【情景4-3-2】插入结点是其父结点的左子结点

【处理】:① 对 P 进行右旋

                  ② 将 P 设置为插入结点,得到情景4-3-1

                  ③ 进行情景4-3-1的处理

RBTree插入情景4-3-2示例图

 

(2)代码实现

(后续补充)

3、删除

(1)原理分析

红黑树的删除操作和AVL树的删除操作类似,也包括两部分工作:① 查找目标结点;② 删除后自平衡。

查找目标结点流程和查找操作是一致的,结果主要有两种情况:① 当不存在目标结点时,忽略本次操作; ② 当存在目标结点时,删除后就得做自平衡处理了。删除结点后我们还需要找结点来替代删除结点的位置,不然子树跟父辈结点断开了,除非删除结点刚好没子结点,那么就不需要替代。

【注意】实际进行删除操作时,并不会先进行删除目标结点,再用替代结点连接,这样实际使得过程更加复杂(①释放目标空间;②替代结点重新连接目标空间的父结点和左右子结点;③断开替代结点原连接;④断开目标结点连接)。

实际删除操作是:①找到替代结点,用替代结点的值替换目标结点值;②释放替代结点空间;③断开替代结点连接。

二叉树删除操作找替代结点有3种情情景:

  • 情景1:若删除叶子结点(非NIL结点)

        ① 如果为红色,直接删除即可,不影响黑高值

        ② 如果为黑色,导致黑高失衡,需要平衡调整

  • 情景2:若删除结点只有一个子结点(只有左子树或右子树)

       删除结点只能是黑色,其子结点为红色,否则无法满足红黑树性质。

       处理方法:将红色子结点值拷贝到父结点,实际删除结点操作为删除红色子结点。

  • 情景3:若删除结点有两个子结点

       使用删除结点的前驱或后继结点作为删除的替代结点,转换为情景1或情景2

上述分析过程可以参考下图示例: 

 

删除黑色结点调整情况:

旋转类型定义: 

看兄弟结点(黑色)及其红色结点位置。

平衡情景综合分析:
【情景1】:删除结点是一个黑色根结点(只有一个根结点)。【处理】:直接删除。
【情景2-1】:删除结点是黑色叶子结点,兄弟为黑色,兄弟有红色子结点

(1)  LL 型   【处理】:右旋 + 爷孙变黑,兄变父色

(2)LR 型  【处理】:左旋 + 右旋 +侄变父色,父变黑色

【情景2-2-1】:删除结点是黑色叶子结点,兄弟为黑色,兄弟无红色子结点,父结点是红色。

        【处理】:父变黑,兄变红

 【情景2-2-2】:删除结点是黑色叶子结点,兄弟为黑色,兄弟无红色子结点,父结点是黑色。

         【处理】:① 把兄弟结点染红;②把父结点当作被新删除结点,递归前面的方法,进行相应                             处理,直至遇到红色父结点并将其染黑,或遇到根结点。

 【情景3】:删除结点是黑色叶子结点,兄弟为红色

         【处理】:兄弟和右侄颜色互换 + 右旋

删除结点的步骤:

1.没有找到删除结点,则直接返回。

2.如果删除的是唯一根结点,释放空间并root置空返回;

3.删除叶子结点

4.删除只有一个子结点的节点。

5.删除有两个子结点的节点。

(2)代码实现

 辅助函数:

RBNode* FindTreeNode(int val);//查找删除结点
RBNode* FindProvNode(RBNode* node);//查找前驱结点
RBNode* FindLaterNode(RBNode* node);//查找后继结点

获得替代结点方法:目的是减少调整次数

  • 先找前驱,如果找到以下两种情况则返回前驱:①红色叶子结点;②有一个红色叶子结点的黑色结点
  • 否则返回后继。

(实现代码后续补充)

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

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

相关文章

Java实现海南旅游景点推荐系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

YUM仓库和NFS共享

目录 一、yum仓库 1. yum仓库介绍 1.1 简介 1.2 实现过程 1.3 实现安装服务 2. yum配置文件及命令 2.1 yum配置文件 2.1.1 yum主配置文件 2.1.2 仓库设置文件 2.1.3 日志文件 2.2 yum命令详解 2.2.1 查询 2.2.2 yum安装升级 2.2.3 软件卸载 3. 搭建仓库的方式 …

使用 Categraf 采集 Nginx 指标

1. 前言 工作中需要监控 Nginx 的指标&#xff0c;选用的指标采集器是 Categraf&#xff0c;特此记录下&#xff0c;以备后用。 此文档并未详细记录详细的操作细节&#xff0c;只记录了大概的操作步骤&#xff0c;仅供参考。 2. 采集基础指标 2.1. 暴露 Nginx 自带的指标采…

SparkSQL——DataFrame

DataFrame Dataframe 是什么 DataFrame 是 SparkSQL中一个表示关系型数据库中 表的函数式抽象, 其作用是让 Spark处理大规模结构化数据的时候更加容易. 一般 DataFrame可以处理结构化的数据, 或者是半结构化的数据, 因为这两类数据中都可以获取到 Schema信息. 也就是说 DataFra…

Kafka系列(四)

本文接kafka三&#xff0c;代码实践kafkaStream的应用&#xff0c;用来完成流式计算。 kafkastream 关于流式计算也就是实时处理&#xff0c;无时间概念边界的处理一些数据。想要更有性价比地和java程序进行结合&#xff0c;因此了解了kafka。但是本人阅读了kafka地官网&#…

【每日一题】2744. 最大字符串配对数目-2024.1.17

题目&#xff1a; 2744. 最大字符串配对数目 给你一个下标从 0 开始的数组 words &#xff0c;数组中包含 互不相同 的字符串。 如果字符串 words[i] 与字符串 words[j] 满足以下条件&#xff0c;我们称它们可以匹配&#xff1a; 字符串 words[i] 等于 words[j] 的反转字符…

Pytorch各种Dropout层应用于详解

目录 torch框架Dropout functions详解 dropout 用途 用法 使用技巧 参数 数学理论公式 代码示例 alpha_dropout 用途 用法 使用技巧 参数 数学理论公式 代码示例 feature_alpha_dropout 用途 用法 使用技巧 参数 数学理论 代码示例 dropout1d 用途 用…

Windows无法登录管理路由器故障排查

问题描述 家里的路由器使用拨号上网&#xff0c;路由器DHCP分发IP的范围是192.168.1.0/24。默认使用192.168.1.1管理路由器。然后拨号上网成功后&#xff0c;修改了私网IP的分发范围&#xff1a;192.168.5.1-192.168.5.10。为了防止有人蹭网&#xff0c;只分配的10个IP地址。修…

rust跟我学三:文件时间属性获得方法

图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎样获得杀毒软件的病毒库时间的。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址…

推荐几个Github高星GoLang管理系统

在Web开发领域&#xff0c;Go语言&#xff08;Golang&#xff09;以其高效、简洁、高并发等特性逐渐成为许多开发者的首选语言。有许多优秀的Go语言Web后台管理系统&#xff0c;这些项目星星众多&#xff0c;提供了丰富的功能和良好的代码质量。本文将介绍一些GitHub高星的GoLa…

新品新品新品来袭PFA大口试剂瓶100ml

大口瓶&#xff0c;方便清洗&#xff0c;满足颗粒数要求。

excel(vab)删除空行

删除第一、二、三列位空的所有行&#xff08;8000)行范围以内 代码如下&#xff1a; Sub Macro1()Dim hang As Integer For hang 8000 To 1 Step -1If Sheet1.Cells(hang, 1) "" And Sheet1.Cells(hang, 2) "" And Sheet1.Cells(hang, 3) "&quo…

SDRAM小项目——命令解析模块

简单介绍&#xff1a; 在FPGA中实现命令解析模块&#xff0c;命令解析模块的用来把pc端传入FPGA中的数据分解为所需要的数据和触发命令&#xff0c;虽然代码不多&#xff0c;但是却十分重要。 SDRAM的整体结构如下&#xff0c;可以看出&#xff0c;命令解析模块cmd_decode负责…

民营经济迎来新发展,创维汽车创始人黄宏生谈创业之道

2024年1月15日&#xff0c;上海高金金融研究院民营经济研究中心高净值研究院年度大咖论坛正式召开&#xff0c;多位来自不同行业的优秀民营企业家在本次论坛上分享企业的创新与发展之道。创维集团、创维汽车创始人黄宏生先生作为本次论坛的首位分享嘉宾&#xff0c;为其他奋斗创…

【技术分享】远程透传网关-单网口快速实现三菱 FX3U 网口PLC程序远程上下载

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台三菱 FX3U PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09; …

Docker部署Traefik结合内网穿透远程访问Dashboard界面

文章目录 前言1. Docker 部署 Trfɪk2. 本地访问traefik测试3. Linux 安装cpolar4. 配置Traefik公网访问地址5. 公网远程访问Traefik6. 固定Traefik公网地址 前言 Trfɪk 是一个云原生的新型的 HTTP 反向代理、负载均衡软件&#xff0c;能轻易的部署微服务。它支持多种后端 (D…

P9852 [ICPC2021 Nanjing R] Windblume Festival 题解(SPJ)

[ICPC2021 Nanjing R] Windblume Festival 单击此处下载原神 题面翻译 给一个长度为 n n n 环形整数序列 a a a, 每次操作可以任意选择一个下标 x x x&#xff0c;令 $ a_x a_x - a_{(x\bmod n)1}$&#xff0c;之后移除 a ( x m o d n ) 1 a_{(x\bmod n)1} a(xmodn)1​…

MDT的驱动管理和自动匹配

在企业的生产环境中&#xff0c;我们经常会遇到在一个公司中&#xff0c;有很多电脑不是同一个品牌的。有DELL&#xff0c; Lenovo等等诸多品牌。 如果是在小的企业或者组织里&#xff0c;计算机型号单一&#xff0c;我们就可以直接导入驱动&#xff0c;然后直接部署到系统里。…

探索Vue3:深入理解响应式语法糖

🚀 欢迎来到我的专栏!专注于Vue3的实战总结和开发实践分享,让你轻松驾驭Vue3的奇妙世界! 🌈✨在这里,我将为你呈现最新的Vue3技术趋势,分享独家实用教程,并为你解析开发中的难题。让我们一起深入Vue3的魅力,助力你成为Vue大师! 👨‍💻💡不再徘徊,快来关注…

代码随想录算法训练营第三十六天|435. 无重叠区间、763.划分字母区间、56. 合并区间

题目&#xff1a;435. 无重叠区间 文章链接&#xff1a;代码随想录 视频链接&#xff1a;LeetCode:435.无重叠区间 题目链接&#xff1a;力扣题目链接 图释&#xff1a; class Solution { public:static bool cmp(const vector<int>&a, const vector<int>…