首页/新闻资讯/正文详情

C++进阶——红黑树

发布时间:2026/9/27 6:05:43 来源:云帆数科 栏目:资讯中心
C++进阶——红黑树
一、红黑树的概念红黑树是一棵二叉搜索树他的每个节点增加一个数据来存储颜色可以是红色或者黑色。通过对任何一条从根到叶子的路径上各个结点的颜色进行约束红黑树确保没有一条路径会超出其他路径2倍的长度1.1 红黑树的规则每个节点不是红色就是黑色根节点是黑色的如果一个节点是红的他的孩子节点就是黑色的这意味着任意一条路径不能出现连续的红色节点对任意一个节点从该节点到其所有NULL节点的简单路径上均包含相同数量的黑色节点当我们能时刻满足这四条规则时我们就能确保树上没有一条路径会超出其他路径2倍的长度。1.2 红黑树的效率假设N是红黑树树中结点数量h是最短路径长度则2^h-1N2^(2*h)-1,由此推出h大约为logN也就意味着红黑树增删查改最坏也就是走最长路径2*logN那么时间复杂度还是OlogN红黑树的表达相对AVL树要抽象一些AVL树通过控制高度差直观地控制了平衡。红黑树通过4条规则的约束实现了近似平衡它们的效率都是同一档次但红黑树插入节点时旋转次数更少二、红黑树的实现2.1 红黑树的结构enum Color { RED, BLACK }; templateclass K,class V struct RBTreeNode { pairK, V _kv; Color _col; RBTreeNodeK, V* _parent; RBTreeNodeK, V* _left; RBTreeNodeK, V* _right; RBTreeNode(const pairK,V kv) :_kv(kv) ,_parent(nullptr) ,_left(nullptr) ,_right(nullptr) { } }; templateclass K,class V class RBTree { typedef RBTreeNodeK, V Node; public: RBTree(Node* rootnullptr) :_root(root) { } private: Node* _root; };2.2 红黑树的插入2.2.1 节点插入的大概过程插入一个值按二叉搜索树规则插入插入后只需观察是否符合红黑树的四条规则如果是空树插入新增节点是黑色节点。如果不是空树选中节点必须是红色节点若插入黑色节点会破坏规则4非空树插入后新增节点的父节点如果是黑色就未破坏规则插入结束若父节点是红色的则违反规则3。据下图c是红色p是红色g必为黑色2.2.2 情况1变色若c、p、u均为红色节点g为黑色节点就将p、u变黑g变红再将g变为新的c向上更新2.2.3 情况2单旋变色c、p为红g为黑u不存在或u为黑u不存在c必为新增节点因为若c为原来的g节点那么它因为孩子节点变色而变红原来是黑色节点但u的分支后面没有黑色节点了不满足每条分支黑色节点数量相等u存在且为黑c一定不是新增节点2.2.4 情况3双旋变色c、p为红g为黑u不存在或存在为黑2.3 红黑树的验证规则1枚举颜色类型天然保证了颜色只有黑色和红色规则2可直接验证规则3前序遍历检查遇到红色节点就查孩子不太方便可反过来检查父节点颜色前序遍历遍历时用形参记录当前节点到根黑色节点数量直到空节点再选任意一条路径黑色节点作为参考值依次比较三、全部实现代码#pragma once #includeiostream #includecassert using namespace std; enum Color { RED, BLACK }; templateclass K,class V struct RBTreeNode { pairK, V _kv; Color _col; RBTreeNodeK, V* _parent; RBTreeNodeK, V* _left; RBTreeNodeK, V* _right; RBTreeNode(const pairK,V kv) :_kv(kv) ,_parent(nullptr) ,_left(nullptr) ,_right(nullptr) { } }; templateclass K,class V class RBTree { typedef RBTreeNodeK, V Node; public: RBTree(Node* rootnullptr) :_root(root) { } bool Insert(const pairK, V kv) { Node* newnode new Node(kv); newnode-_col RED; if (_root nullptr) { newnode-_col BLACK; _root newnode; return true; } Node* pcur _root; Node* parent pcur; while (pcur) { parent pcur; if (pcur-_kv.first kv.first) pcur pcur-_right; else if (pcur-_kv.first kv.first) pcur pcur-_left; else { delete newnode; return false; } } //开始插入 pcur newnode; pcur-_parent parent; if (parent-_kv.first kv.first) parent-_left pcur; else parent-_right pcur; while (parent parent-_col ! BLACK) { Node* g parent-_parent; Node* u nullptr; if (g) { if (parent g-_left)u g-_right; else u g-_left; if (u u-_col RED g-_col BLACK)//情况1p、c、u、都是红色g为黑色 { parent-_col BLACK; u-_col BLACK; g-_col RED; pcur g; parent g-_parent; } else if (parentg-_leftpcurparent-_left)//情况2单旋变色 { RotateR(parent); parent-_col BLACK; g-_col RED; break; } else if (parent-_right pcur g-_right parent) { RotateL(parent); parent-_col BLACK; g-_col RED; break; } else if (parent-_rightpcurg-_leftparent)//情况三双旋变色 { RotateL(pcur); RotateR(pcur); pcur-_col BLACK; g-_col RED; break; } else if (parent-_left pcur g-_right parent) { RotateR(pcur); RotateL(pcur); pcur-_col BLACK; g-_col RED; break; } } } _root-_col BLACK; return true; } void Print(Node* root) { if (root nullptr) return; Print(root-_left); cout root-_kv.first : root-_kv.second ; Print(root-_right); } Node* root() { return _root; } Node* Find(const K key) { Node* pcur _root; while (pcur) { if (pcur-_kv.first key) pcur pcur-_left; else if (pcur-_kv.first key) pcur pcur-_right; else return pcur; } return nullptr; } bool Isrbtree(Node* root) { if (_root nullptr)return true; if (root-_col ! BLACK)return false; int refnum 0; Node* cur root; while (cur ! nullptr) { if (cur-_col BLACK)refnum; cur cur-_left; } return Preorder(root,0,refnum); } private: bool Preorder(Node* root, int num, const int ref) { if (root nullptr) { return num ref; } if (root-_col RED root-_parent-_col ! BLACK) { cout 出现连续红色节点 endl; return false; } if (root-_col BLACK) return Preorder(root-_left, num 1, ref) Preorder(root-_right, num 1, ref); if (root-_col RED) return Preorder(root-_left, num, ref) Preorder(root-_right, num, ref); } void RotateR(Node* cur) { Node* parent cur-_parent; Node* grandpa parent-_parent; parent-_left cur-_right; parent-_parent cur; if (cur-_right) cur-_right-_parent parent; if (grandpa) { if (grandpa-_right parent) grandpa-_right cur; else grandpa-_left cur; } else _root cur; cur-_parent grandpa; cur-_right parent; } void RotateL(Node* cur) { Node* parent cur-_parent; Node* grandpa parent-_parent; parent-_right cur-_left; parent-_parent cur; if (cur-_left) { cur-_left-_parent parent; } if (grandpa) { if (grandpa-_right parent) grandpa-_right cur; else grandpa-_left cur; } else _root cur; cur-_parent grandpa; cur-_left parent; } Node* _root; };

相关推荐

Open CoDesign AGENTS.md v2 更新计划:如何让 Codex 代理跟随 v0.2 本地设计代理架构
Open CoDesign AGENTS.md v2 更新计划:如何让 Codex 代理跟随 v0.2 本地设计代理架构

人工智能AI 应用桌面应用 【免费下载链接】open-codesign Open-source Claude Design alternative. One-click import your Claude Code / Codex API key. Prompt → prototype / slides / PDF. Multi-model (Claude, GPT, Gemini, Kimi, GLM, Ollama). BYOK, local-first, MIT… · 2026/9/27 6:05:43

Airgorah IPC协议深度剖析:WiFi安全审计工具的4字节长度前缀JSON帧与SO_PEERCRED身份验证完整指南
Airgorah IPC协议深度剖析:WiFi安全审计工具的4字节长度前缀JSON帧与SO_PEERCRED身份验证完整指南

Airgorah IPC协议深度剖析:WiFi安全审计工具的4字节长度前缀JSON帧与SO_PEERCRED身份验证完整指南 【免费下载链接】airgorah A WiFi security auditing software 项目地址: https://gitcode.com/gh_mirrors/ai/airgorah Airgorah 是一款用 Rust 编写的 Linu… · 2026/9/27 6:05:37

网站主机免备案吗?一文搞懂避坑指南
网站主机免备案吗?一文搞懂避坑指南

网站主机免备案吗?一文搞懂避坑指南 别被那些花里胡哨的模板骗了,看着好看,真用起来全是坑。 很多老板觉得,只要服务器选对了,网站就能直接跑,不用管什么备案。 今天咱就把【网站主机免备案吗】这事掰开了揉碎了讲清楚,让你 一文搞懂… · 2026/9/27 6:05:37

任丘市网站建设价格真相:3个方案对比,源码下载避坑指南
任丘市网站建设价格真相:3个方案对比,源码下载避坑指南

任丘市网站建设价格真相:3个方案对比,源码下载避坑指南 手里有预算,心里没底,这是大多数任丘市老板找建站公司的真实状态。很多人一上来就问:“做个网站多少钱?”但真正让你头疼的不是报价单上的数字,而是 自己不会代码想做网站 ,却又怕被忽悠。… · 2026/9/27 6:43:52

焊接件表面缺陷检测数据集zip实战:从解压到YOLO训练避坑指南
焊接件表面缺陷检测数据集zip实战:从解压到YOLO训练避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:43:40

软考高级系统架构设计师:架构决策能力实战训练指南
软考高级系统架构设计师:架构决策能力实战训练指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:43:40

AutoSAR架构拆解:从分层设计到NvM与RTE实战避坑指南
AutoSAR架构拆解:从分层设计到NvM与RTE实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:43:34

Cortex-M7与芯骊DSP实时控制选型实战指南
Cortex-M7与芯骊DSP实时控制选型实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:43:34

ESP32与INMP441语音采集实战:I2S接线、配置与避坑指南
ESP32与INMP441语音采集实战:I2S接线、配置与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 6:43:28

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码