数据结构: 红黑树

目录

1.红黑树概念

2.红黑树性质

3.调整

1.如果p和u都是红色,将其都改为黑色即可,然后向上调整

2.如果p红(u黑/u不在),这时候左子树两红,于是给右子树一个红(旋转+变色)

2.1右单旋 + 变色- p变黑, g变红, 达到给右子树一个红节点的效果, 并保持每条路径上黑色节点的个数相同

2.2左右双旋转 + 变色

2.3左单旋 + 变色

2.4右左双选 + 变色

4.红黑树的简单实现

4.1红黑树的定义

4.2相关功能

插入

检查

获取最左/右侧的节点

检查树种是否存在data节点

4.3默认成员函数

测试用例:

1.插入

2.检查

3.获取最左/右侧节点

4.在树种查找节点


1.红黑树概念

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

2.红黑树性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

最短路径: 全黑

最长路径: 一黑一红交替

红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍

红黑树优势: 旋转次数更少

新插入的节点默认是红色

--1.如果是黑色, 一定违反了规则4 会影响所有路径

--2.如果是红色, 当插入到红色节点后面,违反规则3 , 当插入到黑色节点的后面,不违反规则

3.调整

什么时候需要修改红黑树?--当插入到红色节点后面的时候

1.如果p和u都是红色,将其都改为黑色即可,然后向上调整

  • -然后将g改为红(g原来为黑,我们已经把p,u改为黑了,会多一个黑节点,违反规则4,需要把g改为红)
  • -当然改为红后,g的p可能也是红,继续往上调整即可(把cur = g),如果最后调到根,要将根变黑

2.如果p红(u黑/u不在),这时候左子树两红,于是给右子树一个红(旋转+变色)

-这种情况讨论cur的插入位置 ,来决定其需要怎么旋转(单旋,双旋)

--p是g的左 ,且插入的节点在左子树

2.1右单旋 + 变色
- p变黑, g变红, 达到给右子树一个红节点的效果, 并保持每条路径上黑色节点的个数相同

2.2左右双旋转 + 变色

--p是g的右, 且插入的节点在右子树

2.3左单旋 + 变色

2.4右左双选 + 变色

4.红黑树的简单实现

4.1红黑树的定义

节点

RBTree

4.2相关功能

插入

1.找到节点的位置

2.链接节点

3.判断此时p是不是红色, 且存在 (默认插入的节点是红色), 是的话就需要调整

  --p,u存在且都为红 ===> 直接将p,u变为黑色,g变红色, 然后向上调整,

  如果调到根(要将其变黑)

  --p红, u红/u不在    ===> 对插入节点位置进行讨论

1.p是g的左, cur是 p的左  ===> g右单旋

2.p是g的左, cur是p的右   ===>  p左旋, g右旋

3.p是g的右, cur是p的右   ===>  g左单旋

4.p是g的右, cur是p的左   ===>  p右旋,g左旋

代码:

1.找到节点的位置 2.链接节点

​​​​​​​​​​​​​​

3.判断此时p是不是红色, 且存在 (默认插入的节点是红色), 是的话就需要调整

效果:

检查

  1. 判断根节点是黑色的(规则2)
  2. 判断有无连续的红色节点(规则3)
  3. 判断每条路径上的黑色节点个数是否相等(规则4)                                                             --这里随便选取一条路径的黑色节点数作为基准值, 用来和对比其它路径黑节点的个数

代码:

	//红黑树的检查bool Is_RBTree() {return _Is_RBTree(_root);}//红黑树的检查bool _Is_RBTree(Node* root){//规则2:根节点是黑色的if (root == nullptr) return true;	if (root->_color != BLACK) return false;//规则3:不能有连续的红色节点//规则4:每条路径上的黑色节点个数相等Node* cur = root; int base_nums = 0;while (cur) {if (cur->_color == BLACK) base_nums++;cur = cur->_left;}Check(root,base_nums,0);}bool Check(Node* root,int base_nums,int block_nums) {if (root == nullptr) {if (base_nums != block_nums) return false;return true;}//检查有没有连续的红色节点if (root->_parent && root->_color == RED && root->_parent->_color == RED)return false;//遇到一个黑色节点就++if (root->_color == BLACK) block_nums++;return Check(root->_left,base_nums,block_nums) && Check(root->_right,base_nums,block_nums);}

获取最左/右侧的节点

	//获取红黑树最左侧节点Node* LeftMost(){Node* cur = _root;//空树if (cur == nullptr) return nullptr;while (cur->_left){cur = cur->_left;}return cur;}//获取红黑树最右侧节点Node* RightMost(){Node* cur = _root;//空树if (cur == nullptr) return nullptr;while (cur->_right){cur = cur->_right;}return cur;}

检查树种是否存在data节点

	//检测红黑树中是否存在值为data的节点Node* Find(const T& data){Node* cur = _root;while (cur){if (cur->_data > data)cur = cur->_left;else if (cur->_data < data)cur = cur->_right;else return cur;}return nullptr;}

4.3默认成员函数

--构造函数

这里传了缺省值(可不写)

--拷贝构造

思路:使用前序遍历, 构造红黑树

--赋值运算符

思路: 交换_root

--析构函数

后序遍历,删除节点

测试用例:

1.插入

2.检查

正常情况:

异常:

屏蔽掉颜色的调整

修改默认生成黑色节点

3.获取最左/右侧节点

4.在树种查找节点

代码:RB-Tree/RB-Tree · 朱垚/数据结构练习 - 码云 - 开源中国 (gitee.com)

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

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

相关文章

UE5 ChaosVehicles载具 实现大漂移 (连载四)

载具设置成前驱模式 前轮摩擦力倍增x5 后轮摩擦力倍增x0.5

网易面试:什么是SPI,SPI和API有什么区别?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 什么是SPI&#xff0c;SPI和API有什么区别&#xff1f; 最近有小…

STM32内部flash闪存的总结

最近在做无人船和机巢远程在线升级的项目&#xff0c;牵扯到flash的操作&#xff0c;特此记录&#xff0c;便于以后查找。IMU也用到过&#xff0c;当时没记录 具体细节看 E:\Documets\AY\a-project\IMU\IMU16500\S0IMU v3.3 study\User\Driver\source eeprom.c E:\Documets\A…

蓝桥杯每日一题2023.10.22

题目描述 灵能传输 - 蓝桥云课 (lanqiao.cn) 题目分析 发现每一次的灵能传输都是对前缀和s[i - 1]和s[i]的一次交换 故为求max(s[i], s[i - 1])的最小值&#xff08;发现当s单调时可以成立&#xff09; 由于s[0]和s[n]的位置不变&#xff0c;但是s[0]和s[n]不一定是最大值或…

怎么写一个可以鼠标控制旋转的div?

说在前面 鼠标控制元素旋转在现在也是一个很常见的功能&#xff0c;让我们从实现div元素的旋转控制开始来了解元素旋转的具体原理和实现方法吧。 效果展示 体验地址 https://code.juejin.cn/pen/7290719197439459386 实现步骤 画一个div 首先我们需要先画一个div&#xff0…

模板再认识

在前面的文章中我写了关于模板的一些简单的认识&#xff0c;现在我们来再次认识模板文章目录 1.非类型模板参数2.模板特化1). 模板特化的写法2). 类模板特化3). 函数模板特化4). 模板全/偏特化 3.模板分离编译 1.非类型模板参数 在模板中还有一种是非类型的模板参数。我们代码…

人工智能(6):机器学习基础环境安装与使用

1 库的安装 整个机器学习基础阶段会用到Matplotlib、Numpy、Pandas等库&#xff0c;为了统一版本号在环境中使用&#xff0c;将所有的库及其版本放到了文件requirements.txt当中&#xff0c;然后统一安装 新建一个用于人工智能环境的虚拟环境 mkvirtualenv ai matplotlib3.8…

DALL·E 3:OpenAI的革命性图像生成模型与ChatGPT的融合

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Unity⭐️Win和Mac安卓打包环境配置

文章目录 🟥 配置Android SDK1️⃣ 配置 SDK Platforms2️⃣ 配置 SDK Tools🎁 Android SDK Build-Tools🎁 Android SDK Command-line Tools(latest)🎁 Android SDK Tools(Obsolete)🟧 配置NDK🟩 配置JDK前情提示: 此方法适用于Windows/Mac 在配置时注意开启 🪜 …

ubuntu安装Anaconda

下载 Anaconda 进入 Ubuntu&#xff0c;自己新建下载路径&#xff0c;输入以下命令开始下载 注意&#xff0c;如果不是 x86_64&#xff0c;需要去镜像看对应的版本&#xff08;https://mirrors.bfsu.edu.cn/anaconda/archive/?CM&OA&#xff09; wget https://mirrors.…

蓝桥杯中级题目之组合(c++)

系列文章目录 数位递增数_睡觉觉觉得的博客-CSDN博客拉线开关。_睡觉觉觉得的博客-CSDN博客蓝桥杯中级题目之数字组合&#xff08;c&#xff09;_睡觉觉觉得的博客-CSDN博客 文章目录 系列文章目录前言一、个人名片二、描述三、输入输出以及代码示例1.输入2.输出3.代码示例 总…

怎么从A和B仓库执行分别fetch操作?

目录 1.问题2.描述3.解决问题 1.问题 我希望从A仓库拉代码后推送到B仓库&#xff0c;结果A仓库代码新增分支后 在执行fetch时默认仓库地址为B仓库&#xff0c;导致fetch失败。 2.描述 在实际项目开发中我们可能会出现需要将同一个服务的代码推送到不同的代码仓库&#xff0c…