【C++进阶06】红黑树图文详解及C++模拟实现红黑树

在这里插入图片描述

一、红黑树的概念及性质

1.1 红黑树的概念

AVL树用平衡因子让树达到高度平衡
红黑树可以认为是AVL树的改良
通过给每个节点标记颜色让树接近平衡
以减少树在插入节点的旋转
在每个结点新增一个存储位表示结点颜色
可以是Red或Black
通过对任何一条从根到叶子的路径上
各个结点着色方式的限制
红黑树确保没有一条路径会比其他路径长出
俩倍,因而是接近平衡的

1.2 红黑树的性质

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

在这里插入图片描述

为啥满足上面性质的红黑树就能保证
其最长路径节点个数不会超过最短路径
节点个数的两倍?

由性质3可得出不能出现连续红色节点
由性质4可得出每条路径有相同黑色节点数量

极限情况下
最短路径:全黑
最长路径:一黑一红

由此可得出
最长路径不会超过最短路径的两倍
在这里插入图片描述

1.3 为什么更常用红黑树而不是AVL树?

AVL树: 是一颗高度平衡的二叉树
查找效率: O ( l o g N ) O(logN) O(logN)
但是这样的效率是在插入元素时
经常性的旋转换来的

红黑树: 是一颗接近平衡的二叉树
假设全部黑节点有N个
整棵树的节点数量:[N, 2N]之间
最短路径长度: O ( l o g N ) O(logN) O(logN)
最长路径长度: O ( 2 l o g N ) O(2logN) O(2logN)
查找效率: O ( 2 l o g N ) O(2logN) O(2logN)

10亿数据AVL树最多查找30次
红黑树最多也就查找60次
对于cpu的运行速度来说几乎可以忽略不计
但红黑树的规则相对于AVL树没那么严格
在插入元素时,不会经常旋转
所以综合而言红黑树更胜一筹

如图: 对于AVL树必定旋转
红黑树则不用
在这里插入图片描述

二、红黑树模拟实现的基本框架

2.1 红黑树节点的定义

跟AVL树一样
只是AVL树采用平衡因子
让树达到平衡
而红黑树对节点进行颜色标记
让树达到平衡
定义一个枚举表示节点颜色

enum colour
{RED,BLACK,
};template <class K, class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent; // 三叉链pair<K, V> _kv;colour _col;RBTreeNode(const pair<K, V>& kv): _left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED){}
};template <class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:
private:Node* _root = nullptr;
};

2.2 红黑树的插入

还是和AVL树一样

	bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first) // 插入节点比当前节点大往右走, 小往左走{parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}// 链接cur = new Node(kv);if (parent->_kv.first > kv.first){parent->_left = cur;}else{parent->_right = cur;}// new的节点的parent还指向空cur->_parent = parent;// 插入黑色节点还是红色节点?return true;}

插入走到这里如果是AVL树
此时需要更新平衡因子

红黑树采用的是标记节点颜色
让树达到平衡
需要考虑的是插入什么颜色的节点?

  1. 插入黑色节点
    会违反规则4,影响到每条路径
  2. 插入红色节点
    如果插入节点的父节点也是红色节点
    则会违反规则3影响当前局部节点

很明显插入红色节点更划算
所有插入的节点都默认是红色
如果违反红黑树的规则,再进行调整

三、对插入节点调整的解析

如果插入节点的父节点为黑
则无需处理
如果为红,则分为三种情况

情况一:

cur为红,p为红,g为黑,u存在且为红

cur为当前节点,p为父节点
g为祖父节点,u为叔叔节点
在这里插入图片描述
把p和u变黑,g变红
在这里插入图片描述
如果grandfather的parent也为红
把grandfather改为cur
继续按刚才的步骤往后迭代
在这里插入图片描述
如果grandfather为根节点
把grandfather改为黑色
颜色调整结束
在这里插入图片描述

情况二:

cur为红,p为红,g为黑
u不存在或u存在且为黑

此树可能是完整树也可能是子树
u节点不存在
在这里插入图片描述
p为g的左孩子,cur为p的左孩子
则进行右单旋转
相反
p为g的右孩子,cur为p的右孩子
则进行左单旋转
p、g变色–p变黑,g变红
在这里插入图片描述

在这里插入图片描述
下图则是u节点存在的情况
在这里插入图片描述
c为下面4种情况的
任意一种包含一个黑节点的红黑树
d和e可能是空或者一个红节点
在这里插入图片描述
插入新节点,更新完后
继续往后更新
就是情况二的u存在的情况
在这里插入图片描述

情况三:

cur为红,p为红,g为黑
u不存在或u存在且为黑

跟情况二完全类似
只是情况三为双旋
情况二是单旋

p为g的左孩子,cur为p的右孩子
则针对p做左单旋转
相反
p为g的右孩子,cur为p的左孩子
则针对p做右单旋转

则转换成了情况2
此图为u不存在
u存在参考情况二
在这里插入图片描述

四、红黑树插入代码的全部实现

详解都在代码注释
各位友友们请耐心看完

bool Insert(const pair<K, V>& kv)
{if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first) // 插入节点比当前节点大往右走, 小往左走{parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}// 链接cur = new Node(kv);if (parent->_kv.first > kv.first){parent->_left = cur;}else{parent->_right = cur;}// new的节点的parent还指向空cur->_parent = parent;// 如果新插入节点破坏了红黑树规则// 则更新节点颜色while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;// 情况1:u存在且为红,变色处理,并继续往上处理if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandfather->_col = RED;// 继续往上调整cur = grandfather;parent = cur->_parent;}else // 情况2+3:u不存在或者u存在且为黑,旋转+处理{// 如果插入节点在父节点的左,c、p、g呈一条斜线//     g//   p   u// cif (parent->_left == cur){RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED; }else{// 插入节点在父节点的右,c、p、g呈一条折线//      g//   p      u//     cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;// parent->_col = RED; // 父亲本就是红,变一下双重保险grandfather->_col = RED;}break;}}else // (grandfather->_right == parent){Node* uncle = grandfather->_left;// 情况1:u存在且为红,变色处理,并继续往上处理if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandfather->_col = RED;// 继续往上调整cur = grandfather;parent = cur->_parent;}else // 情况2+3:u不存在或者u存在且为黑,旋转+处理{//   g// u    p//         cif (parent->_right == cur){RotateL(grandfather);grandfather->_col = RED;parent->_col = BLACK;}else{//   g// u     p//     cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}_root->_col = BLACK; // 做个双保险,无论那种情况把根都变成黑的return true;
}

五、红黑树全部代码模拟实现

gitee链接

✨✨✨✨✨✨✨✨
本篇博客完,感谢阅读🌹
如有错误之处可评论指出
博主会耐心听取每条意见
✨✨✨✨✨✨✨✨

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

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

相关文章

PaddleSeg学习4——paddle模型使用TensorRT推理(c++)

paddle模型使用TensorRT推理 1 模型末端添加softmax和argmax算子2 paddle模型转onnx模型3 onnx模型转TensorRT模型3.1 安装TensorRT-8.5.3.13.2 使用 trtexec 将onnx模型编译优化导出为engine模型 4 TensorRT模型推理测试5 完整代码6 测试结果 1 模型末端添加softmax和argmax算…

谁是linux SIGKILL的凶手---linux审计日志排障的杀手锏

一、背景描述 在我们的技术生涯中&#xff0c;总会碰到那精彩的一瞬间&#xff0c;哪怕是一瞬间&#xff0c;曾经的熟悉php内核的同事和今天碰到的排障瞬间&#xff0c;都是我技术生涯中那精彩的一瞬间&#xff0c;写一篇日志记录一下。 今天碰到一个问题&#xff0c;就是采集…

2022 年全国职业院校技能大赛高职组云计算赛项试卷

【赛程名称】云计算赛项第一场-私有云 某企业拟使用OpenStack 搭建一个企业云平台&#xff0c;以实现资源池化弹性管理、企业应用集中管理、统一安全认证和授权等管理。 系统架构如图 1 所示&#xff0c;IP 地址规划如表 1 所示。 图 1 系统架构图 表 1 IP 地址规划 设备…

docker 利用特权模式逃逸并拿下主机

docker 利用特权模式逃逸并拿下主机 在溯源反制过程中&#xff0c;会经常遇到一些有趣的玩法&#xff0c;这里给大家分享一种docker在特权模式下逃逸&#xff0c;并拿下主机权限的玩法。 前言 在一次溯源反制过程中&#xff0c;发现了一个主机&#xff0c;经过资产收集之后&…

[手写爬虫框架],从回忆Python到爬虫原理解析

手写爬虫框架&#xff0c;又名&#xff1a;手写爬虫框架的第1天 数据存储&#xff08;无数据库版&#xff09; HTML正文抽取多媒体文件抽取Email提醒 实战项目&#xff1a;基础爬虫 基础爬虫架构及运行流程URL管理器HTML下载器HTML解析器数据存储器爬虫调度器 从爬虫底层 —&…

网站开发第一弹---HTML01

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;网站开发flask框架 &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现…

基于pytorch的循环神经网络情感分析系统

任务目标 基于给定数据集&#xff0c;进行数据预处理&#xff0c;搭建以LSTM为基本单元的模型&#xff0c;以Adam优化器对模型进行训练&#xff0c;使用训练后的模型进行预测并计算预测分类的准确率。 数据简介 IMDB数据集是一个对电影评论标注为正向评论与负向评论的数据集…

Spring Boot Starter介绍和实战

引言 Spring Boot Starter 是 Spring Boot 提供的一种机制&#xff0c;用于简化和集成应用程序的依赖管理。通过创建自定义的 Starter&#xff0c;可以将一组相关的依赖打包成一个简单的、可重用的模块&#xff0c;使应用程序的配置和依赖管理更加方便。在本文中&#xff0c;我…

【AI视野·今日NLP 自然语言处理论文速览 第七十二期】Mon, 8 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Mon, 8 Jan 2024 Totally 17 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers DeepSeek LLM: Scaling Open-Source Language Models with Longtermism Authors DeepSeek AI Xiao Bi, Deli Ch…

深度卷积神经网络

目录 1.AlexNet 2. 代码实现 1.AlexNet (1)特征提取 (2)选择核函数来计算相关性&#xff1a;怎么判断在高维空间里面两个点是如何相关的&#xff0c;如果是线性模型就是做内积。 (3)凸优化问题 (4)漂亮的定理 丢弃法的作用就是因为模型太大了&#xff0c;使用它来对模型做…

python连接sqlite3工具类

简单使用python连接sqlite3工具类&#xff0c;代码可根据场景自行抽象 #!/usr/bin/env python # -*- coding: utf-8 -*-import sqlite3class SQLiteHandler:# 示例用法default_db_path "example.db"def __init__(self, db_fileNone):self.db_file db_file or self…

Spring面试整理-Spring的AOP

Spring的面向切面编程(AOP)是其核心功能之一,它允许开发者在不改变原有代码的情况下,增加额外的行为(如日志记录、事务管理、安全检查等)。AOP 通过定义"切面"(aspects)和"通知"(advice)来实现这一功能。 AOP概念 切面(Aspect):切面是模块化的…

TCP 和 UDP 的区别

TCP&#xff08;Transmission Control Protocol&#xff09;和UDP&#xff08;User Datagram Protocol&#xff09;是两种主要的传输层协议&#xff0c;它们在网络通信中有一些关键的区别&#xff1a; &#xff08;1&#xff09;http1 / http2 基于 tcp 协议&#xff0c;https …

XCODE IOS 静态链接库替换升级

XCODE 版本15.2. 一个很久需求没更新的IOS 应用&#xff0c;近来有新需求要开发。 拉下代码运行&#xff0c;出现了个BAD_ACCESS错误。出错的位置位于一个调用的第三方的.a静态库内部。因为调用代码并没有修改&#xff0c;很容易想到可能XCODE相关升级&#xff0c;导致的问题。…

无监督学习Principal Component Analysis(PCA)精简高维数据

目录 介绍 一、PCA之前 二、PCA之后 介绍 Principal Component Analysis (PCA) 是一种常用的数据降维和特征提取技术。PCA通过线性变换将高维数据映射到低维空间&#xff0c;从而得到数据的主要特征。PCA的目标是找到一个正交基的集合&#xff0c;使得将数据投影到这些基…

Android Studio 分别运行flutter 的debug和release版本

前言 由于在Android Studio 没找到运行release版本的入口,现在通过命令行运行 1.release版本 运行release版本的话直接执行下面命令3 flutter run --release相关命令统计 1.生成apk flutter build apk2.安装apk&#xff1a; flutter install3.运行release版本 flutter …

【期末不挂科-单片机考前速过系列P11】(第十一章:单片机的并行拓展例题)经典例题盘点(带图解析)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

初探UAF漏洞(3)

构造exp #include <iostream> #include <Windows.h>typedef void(*FunctionPointer) ();typedef struct _FAKE_USE_AFTER_FREE {FunctionPointer countinter;char bufffer[0x54]; }FAKE_USE_AFTER_FREE, * PUSE_AFTER_FREE;void ShellCode() {_asm{noppushadmov e…

github上的python图片转excel,pytesseract安装相关问题

问题1&#xff1a;明明都pip install pytesseract&#xff0c;但是就是安装不上 pytesseract 未安装链接: https://pan.baidu.com/s/1I4HzCgO4mITWTcZFkdil6g?pwdafes 提取码: afes 安装后一路next&#xff0c;然后配置环境变量 C:\Program Files\Tesseract-OCR新建一个系统…

第十九章 类的继承

文章目录 一、继承二、原型三、原型和实例关系的检测 一、继承 面向对象三大特点&#xff1a;封装&#xff0c;继承&#xff0c;多态 封装&#xff1a;打包继承&#xff1a;一个对象A不具有某个功能a&#xff0c;通过某种方式使用了对象B的a功能 的过程多态&#xff1a;对象或…