当前位置: 首页 > news >正文

【C++杂货铺】红黑树


目录

🌈前言🌈 

📁 红黑树的概念

📁 红黑树的性质

📁 红黑树节点的定义

📁 红黑树的插入操作

📁 红黑树和AVL树的比较

📁 全代码展示

📁 总结


🌈前言🌈 

        欢迎大家观看本期【C++杂货铺】,本期内容将讲解二叉搜索树的进阶——红黑树。红黑树是一种二叉搜索树,通过控制每个节点的颜色,来调整整棵树的高度。

        红黑树是set和map实现的底层实现,在下一期内容,我们将讲解STL中set和map的模拟实现。如果你对二叉搜索树还不是很了解,可以快速阅览下面这篇文章;

【C++杂货铺】二叉搜索树-CSDN博客

📁 红黑树的概念

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

📁 红黑树的性质

1. 每个节点不是红色就是黑色;

2. 根节点是黑色的;

3. 如果一个节点是红色的,那么它的两个孩子节点是黑色的;

4. 对于每个节点,从该节点到其他所有后代叶节点的简单路径上,均包含相同数目的黑色节点个数;

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

📁 红黑树节点的定义

// 节点的颜色
enum Color{RED, BLACK};
// 红黑树节点的定义
template<class ValueType>
struct RBTreeNode
{RBTreeNode(const ValueType& data = ValueType(),Color color = RED): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _color(color){}RBTreeNode<ValueType>* _pLeft;   // 节点的左孩子RBTreeNode<ValueType>* _pRight;  // 节点的右孩子RBTreeNode<ValueType>* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给
出该字段)ValueType _data;            // 节点的值域Color _color;               // 节点的颜色
};

📁 红黑树的插入操作

        红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可分为两步:

1. 按照二叉搜索树规则插入新节点;

        新插入节点的默认颜色是红色。因为红色容易控制规则,如果默认插入黑色,需要保证从当前节点到叶子节点具有相同的黑色节点个数,不易控制。

        即先保证性质4不被违反,再来判断性质3是否被违反,如果违反就进行调整。

2. 检测新节点插入后,红黑树的性质是否遭到破坏。

        如果双亲节点的颜色是黑色,没有违反规则,则不需要调整;当新插入节点的双亲节点颜色为红色时,就违反了性质3,即不能有连续在一起的红色节点,此时需要进行调整,可分为两种情况:

约定:cur为当前节点,p为父亲节点,g为祖父节点,u为叔叔节点

● 情况1:cur为红,p为红,g为黑,u存在且为红

● 情况2:cur为红,p为红,g为黑,u存在且为黑 或者 u不存在

        当如子树如下图所示时,需要对红黑树进行双旋,先以p为根进行左旋,再以g为根进行右旋。下图是p在g的左子树的情况,考虑一下p在g的右子树,且cur为p的左子树的情况。

📁 红黑树和AVL树的比较

        红黑树和AVL数都是搞笑的平衡二叉树,增删查改的时间复杂度都是O(log N),红黑树不追求绝对平衡,其只需要保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL数更优,而且红黑树的实现比较简单,所以实际应用中红黑树更多。

        map和set的底层就是红黑树。

📁 全代码展示

template <class T>
struct RBTreeNode
{typedef RBTreeNode<T> Node;RBTreeNode(const T& val = T()):_left(nullptr), _right(nullptr), _parent(nullptr), _val(val), _color(RED){}Node* _left;Node* _right;Node* _parent;T _val;Color _color;
};template<class T>
class RBTree
{typedef RBTreeNode<T> Node;
public:bool Insert(const T& val){if (_root == nullptr){_root = new Node(val);_root->_color = Black;return true;}Node* cur = _root;Node* parent = nullptr;while (cur){if (cur->_val > val){parent = cur;cur = cur->_left;}else if (cur->_val < val){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(val);if (parent->_val < val){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//调整颜色,不能出现连续的红色while (parent && parent->_color == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){//叔叔在右边//1. 叔叔存在,且为红色Node* uncle = grandfather->_right;if (uncle && uncle->_color == RED){grandfather->_color = RED;uncle->_color = parent->_color = Black;cur = grandfather;parent = cur->_parent;}//2. 叔叔存在,且为黑色  ||  叔叔不存在else{/*gp		uc  */if (cur == parent->_left){RotateR(grandfather);parent->_color = Black;grandfather->_color = RED;}/*gp		uc*/else{RotateL(parent);RotateR(grandfather);cur->_color = Black;grandfather->_color = RED;}break;}}else{//叔叔在左边//1. 叔叔存在,且为红色Node* uncle = grandfather->_left;if (uncle && uncle->_color == RED){grandfather->_color = RED;parent->_color = uncle->_color = Black;cur = grandfather;parent = cur->_parent;}//2. 叔叔存在,且为黑色  ||  叔叔不存在else{/*gu		pc*/if (cur == parent->_right){RotateL(grandfather);parent->_color = Black;grandfather->_color = RED;}/*gu		pc   */else{RotateR(parent);RotateL(grandfather);cur->_color = Black;grandfather->_color = RED;}break;}}}_root->_color = Black;return true;}//遍历
void InOrder()
{_InOrder(_root);cout << endl;
}bool isBalance()
{if (_root == nullptr){return true;}int BlackNum = 0;Node* cur = _root;while (cur){if (cur->_color == Black)BlackNum++;cur = cur->_right;}return _isBalance(_root,0,BlackNum);
}protected:bool _isBalance(Node* root,int count , const int& BlackNum){if(root == nullptr){if (count != BlackNum)return false;return true;}if (root->_color == RED && root->_parent->_color == RED){cout << "red" << endl;return false;}if (root->_color == Black)count++;return _isBalance(root->_left,count,BlackNum)&& _isBalance(root->_right,count,BlackNum);}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_val << endl;_InOrder(root->_right);}//左单旋void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* pparent = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;_root->_parent = nullptr;}else{if (parent == pparent->_right){pparent->_right = subR;}else{pparent->_left = subR;}subR->_parent = pparent;}}//右单旋void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;Node* pparent = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (parent == pparent->_right){pparent->_right = subL;}else{pparent->_left = subL;}subL->_parent = pparent;}}
private:Node* _root = nullptr;
};

📁 总结

        以上就是本期【C++杂货铺】的主要内容了,讲解了红黑树如果优化二叉搜索树,红黑树的概念,红黑树实现插入,以及红黑树的高度平衡调整,此外模拟实现了红黑树。

        如果感觉本期内容对你有帮助,欢迎点赞,收藏,关注Thanks♪(・ω・)ノ

相关文章:

【C++杂货铺】红黑树

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 红黑树的概念 &#x1f4c1; 红黑树的性质 &#x1f4c1; 红黑树节点的定义 &#x1f4c1; 红黑树的插入操作 &#x1f4c1; 红黑树和AVL树的比较 &#x1f4c1; 全代码展示 &#x1f4c1; 总结 &#x1f308;前言…...

css--控制滚动条的显示位置

各种学习后的知识点整理归纳&#xff0c;非原创&#xff01; ① direction属性 滚动条在左侧显示② transform:scaleY() 滚动条在上侧显示 正常的滚动条会在内容超出规定的范围后在区域右侧和下侧显示在有些不正常的需求下会希望滚动条在上侧和左侧显示自己没有想到好的解决方案…...

华为设备display查看命令

display version //查看版本信息 display current-configuration //查看配置详情 display this //查看当前视图有效配置 display ip routing-table //查看路由表 display ip routing-table 192.168.3.1 //查看去往3.1的路由 display ip interface brief //查看接口下ip信息 dis…...

自动攻丝机进出料激光检测 进料出料失败报警循环手动及关闭报警退出无限循环

/**************进料检测********************/ /***缺料无限次循环 手动退出 超时报警*******/ void check_Pon() // { zstatus0; //报警计数器归零 Signauto1; …...

2024年去除视频水印的5种方法

如果你从事电影剪辑或者视频编辑工作&#xff0c;你经常需要从优酷、抖音、TikTok下载各种视频片段……。 通常这些视频带有水印和字幕。一些免费软件如CapCut、canva、Filmora也会给你制作的视频打上水印&#xff0c;这些水印嵌入在视频内部。 2024年去除视频水印的5种方法 …...

怎么用电脑接收手机文件 用备忘录传输更舒服

在这个数字化时代&#xff0c;手机已经成为我们随身携带的“百宝箱”&#xff0c;里面装满了各种重要的文件、资料和信息。然而&#xff0c;有时我们需要在电脑上处理这些文件&#xff0c;比如编辑文档、制作PPT或是查看照片。那么&#xff0c;如何在电脑与手机之间实现文件的顺…...

微信小程序、uniapp密码小眼睛

直接上代码喔喔喔喔喔喔喔喔~~ <input name"username" password"{{passwordHideShow}}" placeholder-style"color:#bdbdbd" type"text"maxlength"20" value"{{passwordNumber}}" bindinput"passwordInput…...

【手势操作-复习前一天的内容-预习今天的内容 Objective-C语言】

一、昨天呢,我们学习的是这个,事件 1.事件这一块儿呢,iOS事件,分为三大类, 1)触摸事件 2)加速计事件 3)远程控制事件 2.这个里边呢,我们主要学习的是这个触摸事件,触摸事件里边,就是Touch,touchesBegan:方法里边,有一个touches参数,它是set类型的, 3.Set,…...

​​​【收录 Hello 算法】第 6 章 哈希表

目录 第 6 章 哈希表 本章内容 第 6 章 哈希表 Abstract 在计算机世界中&#xff0c;哈希表如同一位聪慧的图书管理员。 他知道如何计算索书号&#xff0c;从而可以快速找到目标图书。 本章内容 6.1 哈希表6.2 哈希冲突6.3 哈希算法6.4 小结...

rust类型和变量(二)

基础知识 Rust中的变量基础知识 1.在Rust中&#xff0c;使用Iet关键字来声明变量 2.Rust支持类型推导&#xff0c;但你也可以显式指定变量的类型&#xff1a; Ietx:i325;/显式指定x的类型为i32 3.变量名蛇形命名法(Snake Case),i 而枚举和结构体命名使用帕斯卡命名法(Pasca|Ca…...

linux学习:多媒体开发库SDL+视频、音频、事件子系统+处理yuv视频源

目录 编译和移植 视频子系统 视频子系统产生图像的步骤 api 初始化 SDL 的相关子系统 使用指定的宽、高和色深来创建一个视窗 surface 使用 fmt 指定的格式创建一个像素点​编辑 将 dst 上的矩形 dstrect 填充为单色 color​编辑 将 src 快速叠加到 dst 上​编辑 更新…...

基于门控的循环神经网络:LSTM

之前我们介绍了循环神经网络的原理以及实现。但是循环神经网络有一个问题&#xff0c;也就是长期依赖问题。我们之前的01序列预测案例中可以看到&#xff0c;当序列长度到达10以上之后错误就会增多&#xff0c;说明简单的RNN记忆容量较小&#xff0c;当长度更大时就不怎么适用了…...

Web常见的攻击方式及其防御策略

随着互联网技术的快速发展&#xff0c;Web应用已成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;Web应用也面临着各种安全威胁和攻击。了解这些常见的攻击方式&#xff0c;并采取有效的防御策略&#xff0c;对于保护Web应用的安全至关重要。 一、常见的Web攻击方…...

关于SQL

数据库简介&#xff1a; 数据库分类 关系型数据库模型&#xff1a; 优点&#xff1a;易于维护&#xff0c;可以实现复杂的查询 缺点&#xff1a;海量数据 读取写入性能差&#xff0c;高并发下数据库的io是瓶颈 是把复杂的数据结构归结为简单的二元关系&#xff08;即二维表…...

大模型时代下两种few shot高效文本分类方法

介绍近年(2022、2024)大语言模型盛行下的两篇文本分类相关的论文&#xff0c;适用场景为few shot。两种方法分别是setfit和fastfit&#xff0c;都提供了python的包使用方便。 论文1&#xff1a;Efficient Few-Shot Learning Without Prompts 题目&#xff1a;无需提示的高效少…...

Linux0.11 中全局描述符表(GDT)

在Linux内核中&#xff0c;全局描述符表&#xff08;Global Descriptor Table&#xff0c;简称GDT&#xff09;是一个关键的数据结构&#xff0c;主要用于管理处理器的内存段和相关的权限与属性。它属于x86架构中的保护模式特性&#xff0c;允许操作系统对内存访问进行更精细的…...

搜维尔科技:数据手套用于外固定虚拟现实模拟 、外固定增强现实模拟

数据手套用于外固定虚拟现实模拟、外固定增强现实模拟 搜维尔科技&#xff1a;数据手套用于外固定虚拟现实模拟、外固定增强现实模拟...

《三》菜单栏_工具栏_状态栏动作与实现

上期我们创建了辣么多的动作&#xff0c;那么这次我们要是开始实现这些动作&#xff0c;撸起袖子来吧&#xff1a; //菜单动作&#xff08;ACtion&#xff09;QAction *newAct;//新建QAction *openAct;//打开QAction *saveAct;//保存QAction *saveAsAct;//另存为QAction *prin…...

基于NTP服务器获取网络时间的实现

文章目录 1 NTP1.1 简介1.2 包结构1.3 UNIX 时间戳和NTP时间戳 2 代码实现2.1 实现步骤2.2 完整代码 3 结果 在某些场景下&#xff0c;单片机需要通过网络获取准确的时间进行数据同步&#xff0c;例如日志记录、定时任务等。然而&#xff0c;单片机本身无法直接获得准确的标准时…...

Web APIs(获取元素+操作元素+节点操作)

目录 1.API 和 Web API 2.DOM导读 DOM树 3.获取元素 getElementById获取元素 getElementsByTagName获取元素 H5新增方法获取 获取特殊元素 4.事件基础 执行事件 操作元素 修改表单属性 修改样式属性 使用className修改样式属性 获取属性的值 设置属性的值 移除…...

springboot交通道路监测感知与车路协同系统可视化大屏

目录技术架构设计数据采集与处理可视化大屏功能模块系统集成与部署关键技术点测试与迭代项目技术支持源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作技术架构设计 采用SpringBoot作为后端框架&#xff0c;提供RESTful API接口&#xff1b;…...

JPEXS Free Flash Decompiler技术文档贡献者名单:作者与编辑

JPEXS Free Flash Decompiler技术文档贡献者名单&#xff1a;作者与编辑 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款强大的开源Flash反编译工具&…...

OpenClaw进阶:利用GLM-4.7-Flash实现复杂任务链式执行

OpenClaw进阶&#xff1a;利用GLM-4.7-Flash实现复杂任务链式执行 1. 为什么需要链式任务执行 上周我在整理项目文档时&#xff0c;遇到了一个典型的多步骤任务&#xff1a;需要从十几个Markdown文件中提取关键数据&#xff0c;整理成Excel表格&#xff0c;然后根据内容生成分…...

【Python SM9性能生死线】:当SM9签名延迟突破120ms,你必须立即检查的4个Cython绑定陷阱

第一章&#xff1a;Python SM9性能生死线的临界认知SM9作为我国自主设计的标识密码算法标准&#xff08;GB/T 38635–2020&#xff09;&#xff0c;其在Python生态中的实现常因底层运算瓶颈而陷入“可运行但不可用”的灰色地带。性能临界点并非由单一因素决定&#xff0c;而是密…...

效率直接起飞!盘点2026年全民喜爱的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂的AI论文写作工具&#xff0c;实测提速效果惊人&#xff0c;覆盖选题、文献、写作、降重、排版全流程&#xff0c;让你高效搞定论文不再难。 一、全流程王者&#xff1a;一站式搞定论文全链路&#xff08;一天定稿首选&…...

PowerShell效率提升秘籍:10个必备插件让你的终端飞起来

PowerShell效率革命&#xff1a;10款生产力插件深度评测与实战指南 对于每天与终端打交道的开发者来说&#xff0c;PowerShell的默认功能往往难以满足高效开发的需求。本文将深入剖析10款经过实战检验的效率工具&#xff0c;从智能补全到目录导航&#xff0c;从文件操作到命令解…...

OpenClaw对比测试:Qwen3.5-9B与其他模型在自动化任务中的表现

OpenClaw对比测试&#xff1a;Qwen3.5-9B与其他模型在自动化任务中的表现 1. 测试背景与实验设计 最近在搭建个人自动化工作流时&#xff0c;我遇到了一个关键问题&#xff1a;OpenClaw框架下究竟该选择哪个大模型作为决策核心&#xff1f;为了找到答案&#xff0c;我花了三天…...

避坑指南:关系数据库设计中90%人会犯的完整性约束错误(附真实案例)

避坑指南&#xff1a;关系数据库设计中90%人会犯的完整性约束错误&#xff08;附真实案例&#xff09; 在电商大促期间&#xff0c;某平台突然出现大量"幽灵订单"——用户支付成功后订单消失&#xff0c;而库存却异常扣减。技术团队紧急排查发现&#xff0c;问题根源…...

lychee-rerank-mm惊艳效果集:Qwen2.5-VL底座下BF16高精度打分可视化

lychee-rerank-mm惊艳效果集&#xff1a;Qwen2.5-VL底座下BF16高精度打分可视化 想象一下&#xff0c;你有一个包含数百张图片的图库&#xff0c;想快速找出所有“夕阳下的海边剪影”照片。传统方法要么靠记忆&#xff0c;要么一张张翻看&#xff0c;费时费力。现在&#xff0…...

MATLAB中扩展卡尔曼滤波与无迹卡尔曼滤波源代码:一键运行,误差对比及显示最大误差数字图像程...

MATLAB编写的EKF和UKF滤波程序源代码 扩展卡尔曼滤波、无迹卡尔曼滤波的MATLAB程序&#xff0c;有误差对比图像和最大误差数字的显示。 只有一个m文件&#xff0c;打开就能运行。 带中文注释。直接双击EKFUKFComparison.m就能看到两个滤波器在非线性系统里的较量。这个文件里塞…...