C++色彩博弈的史诗:红黑树

红黑树详解 title: 红黑树原理 红黑树提纲 2-3树介绍 红黑树 该博客都是读者具备二分树基础知识前提下写的(不清楚的不要看下面的内容了,看了也不会明白多少的…) 下面都统一用RBTree表示红黑树。 RBTree很多人都觉得难,其实我刚听到的时候也觉得难。因为大家都说难。。。哈哈~开个玩笑 RBTree其实并没有说的那么难,RBTree是23Tree的变种版本。 所以正常的学习流程应该是先从23T... 阅读详情

红黑树是一种自平衡二叉查找树,每个节点都带有颜色属性,颜色或为红色或为黑色,可以理解为 AVL 树的进阶版,建议系统学习完 AVL 树再来看本篇博客

传送门:C++漫步结构与平衡的殿堂:AVL树

1.红黑树的概念

在这里插入图片描述

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是 Red 或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保最长路径的节点数量不超过最短路径节点数量的两倍(刚好两倍是可以的),因而是接近平衡的

一个合格的红黑树需要满足以下条件:

  • 每个结点不是红色就是黑色
  • 根节点是黑色的
  • 如果一个节点是红色的,则它的两个孩子结点必须是黑色的,任何路径都没有连续的红色节点,也就是说可以有连续的黑色节点,但不可能一颗红黑树全是黑色节点
  • 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色节点
  • 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

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

最短路径就是仅由黑色节点构成的路径。因为如果路径中插入红色节点,会使路径变长,而全黑路径不包含额外红色节点,所以是最短的

最长路径是红黑交替出现的路径。即每一个黑色节点后面都跟着一个红色节点(但红色节点后不能再有红色节点)

设最短路径的黑色节点数量为 n ,由于所有路径黑色节点数量相同,最长路径的黑色节点数量也为 n ,那么最长路径由于红黑交替的节点总数最多为 2n 。所以,最长路径的节点个数不会超过最短路径节点个数的两倍

2.红黑树的结构

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)
	{}
};

在节点的定义中,为什么要将节点的默认颜色给成红色的?

红黑树的性质要求从根节点到每个叶子节点的路径上黑色节点数量相同。将新节点设为红色,在插入过程中,如果其父节点是黑色,那么插入红色节点不会影响任何路径上黑色节点的数量,也就不需要对树进行调整来满足红黑树的性质,从而减少了调整的可能性,提高了插入操作的效率

如果新节点是黑色,那么插入后可能会导致某个路径上的黑色节点数量增加,这会引发更复杂的 “双黑” 问题,即删除或插入操作后出现一个节点需要同时承担两个黑色节点的情况,处理起来相对复杂。而默认新节点为红色,出现的问题主要是红节点冲突,处理相对简单,以下的插入会详细解释原因

3.红黑树的插入

typedef RBTreeNode<K, V> Node;
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);
	cur->_col = RED;
	if (parent->_kv.first < kv.first)
	{
		parent->_right = cur;
	}
	else
	{
		parent->_left = cur;
	}

	cur->_parent = parent;

	while (parent && parent->_col == RED)
	{
		Node* grandfather = parent->_parent;
		if (parent == grandfather->_left)
		{
			Node* uncle = grandfather->_right;
			// u存在且为红
			if (uncle && uncle->_col == RED)
			{
				// 变色
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				// 继续向上处理
				cur = grandfather;
				parent = cur->_parent;
			}
			else // u不存在 或 存在且为黑
			{
				if (cur == parent->_left)
				{
					//     g
					//   p
					// c
					RotateR(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//     g
					//   p
					//		c
					RotateL(parent);
					RotateR(grandfather);

					cur->_col = BLACK;
					grandfather->_col = RED;
				}

				break;
			}
		}
		else // parent == grandfather->_right
		{
			Node* uncle = grandfather->_left;
			// u存在且为红
			if (uncle && uncle->_col == RED)
			{
				// 变色
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				// 继续向上处理
				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
				if (cur == parent->_right)
				{
					// g
					//	  p
					//       c
					RotateL(grandfather);
					grandfather->_col = RED;
					parent->_col = BLACK;
				}
				else
				{
					// g
					//	  p
					// c
					RotateR(parent);
					RotateL(grandfather);
					cur->_col = BLACK;
					grandfather->_col = RED;
				}

				break;
			}
		}
	}

	_root->_col = BLACK;

	return true;
}

对于插入的节点,可能会遇到三种情况:

🚩uncle存在且为红
在这里插入图片描述

我们定义插入节点为 cur,其父节点为 parent,父节点的兄弟节点为 uncle,父节点的父节点为 grandfather

当新插入节点的双亲节点颜色为红色时,就违反了不能有连在一起的红色节点,想要尽可能不破坏红黑树的平衡结构的情况下正常插入,那么通过变色解决是最好的

请添加图片描述

不能连续出现红色节点,还要保持每条路径的黑色节点相同,可以将 parent 和 uncle 变黑,grandfather 变红解决

在这里插入图片描述

发现处理完之后,在子树上是保持平衡的,但是 grandfather 又出现了连续红色节点,这是其中一种情况,总共有三种情况:

  1. grandfather 没有父亲,就是根,直接变黑就好了
  2. grandfather 有父亲,父亲是黑色,直接结束
  3. grandfather 有父亲,父亲是红色,重复上述操作

很明显示例就是第三种

🚩uncle不存在

在这里插入图片描述

当 uncle 不存在的时候,发现通过变色已经不能解决问题了,这个时候就要旋转调整结构了,根据 cur 的位置判断进行单旋还是双旋

在这里插入图片描述

然后根据结构性质进行变色即可

🚩uncle存在且为黑
在这里插入图片描述

当 uncle 存在且为黑的时候,情况和 uncle 不存在是一样的

🔥值得注意的是: AVL 树旋转可以根据平衡因子为 2 的相对位置来判断是要单旋还是双旋,红黑树根据 grandfather,parent,cur 的相对位置来判断,也就是要多画图

4.红黑树的删除

红黑树的删除本节不做讲解,有兴趣可参考:《算法导论》或者《STL源码剖析》

传送门:博客园相关讲解

5.红黑树与AVL树的比较

可是红黑树的时间复杂度比AVL树更高啊,为什么反而用的更多?

红黑树AVL树
最长路径不超过最短路径的2倍高度差不超过1
10亿个值10亿个值
2*logN->60logN->30

可以看到数据,性能处理上大概相差两倍,但是要知道 CPU 的性能是很强大的,每秒能处理十几亿的数据,这点差距根本不足为惧,而且红黑树和 AVL 树是处于同一量级的,但是 AVL 树的插入删除需要大量的旋转,控制严格平衡的代价太大,因此使用红黑树更多

6.红黑树的验证

🚩检查是否有连续红色节点

bool CheckColour(Node* root, int blacknum, int benchmark)
{
	if (root == nullptr)
	{
		if (blacknum != benchmark)
			return false;

		return true;
	}

	if (root->_col == BLACK)
	{
		++blacknum;
	}

	if (root->_col == RED && root->_parent && root->_parent->_col == RED)
	{
		cout << root->_kv.first << "出现连续红色节点" << endl;
		return false;
	}

	return CheckColour(root->_left, blacknum, benchmark)
		&& CheckColour(root->_right, blacknum, benchmark);
}

🚩检查是否平衡

bool IsBalance()
{
	return IsBalance(_root);
}

bool IsBalance(Node* root)
{
	if (root == nullptr)
		return true;

	if (root->_col != BLACK)
	{
		return false;
	}

	// 基准值
	int benchmark = 0;
	Node* cur = _root;
	while (cur)
	{
		if (cur->_col == BLACK)
			++benchmark;

		cur = cur->_left;
	}

	return CheckColour(root, 0, benchmark);
}

int Height()
{
	return Height(_root);
}

int Height(Node* root)
{
	if (root == nullptr)
		return 0;

	int leftHeight = Height(root->_left);
	int rightHeight = Height(root->_right);

	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

基于R-CNN深度学习的石头剪刀布手势识别系统:数据集、模型和UI界面的完整实现 本项目的目标是开发一个基于R-CNN深度学习模型的手势识别系统,能够识别石头、剪刀、布三种手势,并通过UI界面让用户能够进行交互。数据集准备与标注:收集包含石头剪刀布手势的图像,并对其进行标注。深度学习模型构建与训练:采用R-CNN模型进行手势的识别和定位。UI界面设计:设计一个简洁的界面,用户可以上传手势图像并进行识别。R-CNN(Region Convolutional Neural Networks)是一个典型的目标检测模型。生成候选区域。 阅读详情

相关推荐

顶刊《会计研究》数据复现|最新上市公司数智化数据

本文基于Python文本分析方法构建了中国A股上市公司数智化指标(1991-2024),通过识别年报中的"机器学习""智能医疗"等关键词,量化企业数字化与智能化融合程度。研究发现数智化企业更倾向于非正式渠道的定性披露以规避风险,该指标为监管完善信披规则提供了参考。研究还揭示了数智化对企业信息披露策略的转变,并提出了未来研究方向,包括数智化对绿色创新、ESG表现等影响机制。数据覆盖非金融类上市公司,采用文本挖掘技术构建结构化指标,为相关领域研究提供了微观基础。

PPdata_Academy的博客 1487

图解红黑树

1.红黑树简介 红黑树(Red Black Tree)是一种含有红黑结点并能自平衡二叉查找树,典型的用途是实现 map。 它必须满足下面规则: 规则1:每个结点要么是黑色,要么是红色。 规则2:根结点是黑色。 规则3:每个叶子结点(NIL)是黑色。 规则4:每个红色结点的两个子结点都是黑色。 规则5:任意一结点到每个叶子结点的路径都包含相同数量的黑结点。 记住上面的规则也不难,我们会发现黑色结点非常特殊,规则1即“非红即黑”,规则2和3即“首尾全黑”,规则4即“红子双黑”,规则5即“路径等黑”。 这些规则

Doublelv 的博客专栏。 2680

【自由谈】城域网IPv6过渡技术——MAP技术(1)

在IPv4向IPv6网络演进的浪潮中,存在着两对主要矛盾的较量,一对是IPv4地址短缺和IPv4业务蓬勃发展之间的矛盾,另一对是IPv6海量的地址空间和IPv6应用的匮乏之间的矛盾。同时两对矛盾又互相制约,IPv4地址共享机制似乎又减缓了IPv6产业链的发展,IPv6产业链的不断发展似乎又在考验着IPv4地址共享机制的部署规模。MAP成为目前兼顾IPv4和IPv6的4voer6场景中最为关注的技术。

韩立金自由谈 3024

红黑树

/枚举//节点颜色RED,BLACK//红黑树节点的定义, _kv(kv){}插入的代码实现检测新节点插入后,红黑树的性质是否造到破坏因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连 在一起的红色节点,此时需要对红黑树分情况来讨论:约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点。

ljw的博客 1475

kettle连接达梦资源库数据库插件

kettle自定义插件plugin database plugin 达梦插件 dm插件

weixin_42122126的博客 2170

Parasoft C++Test软件集成测试(部件测试)_实例讲解

本文以一组功能函数组件作为示例,讲解了如何使用C++Test进行软件集成测试。本文的示例比较简单,但是思路、方法和流程都是通用的,希望对大家有所帮助。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 734

【高阶数据结构】红黑树

红黑树

2203_76003626的博客 1319

【入门AUTOSAR网络管理测试】CANoe测试T_WakeUp时间

随着智能电动汽车行业的快速发展,目前AUTOSAR网络管理也得到了广泛应用,AUTOSAR网络管理测试也是汽车网络测试中非常重要的环节,NM问题导致的汽车ECU不能唤醒、电瓶亏电等问题,对于新入门AUTOSAR网络管理测试的同学不清楚如何开展测试,那么本章节就主要给大家介绍网络管理中T_WakeUp时间如何测试。【入门AUTOSAR网络管理测试】AUTOSAR网络管理规范需求解读。

测试领域技术分享 2136

红黑树介绍

红黑树一、红黑树的概念红黑树的性质红黑树节点的定义红黑树结构二、使用步骤1.引入库2.读入数据总结 一、红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。 红黑树的性质 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点是黑色的 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数

mz474920631的博客 4万+

基于STM32F1XX 、HAL库的LTR-303ALS-01 环境光传感器驱动应用C语言程序设计

printf("制造商ID: 0x%02X\r\n", LTR303_ReadManufacID());printf("器件ID: 0x%02X\r\n", LTR303_ReadPartID());LTR-303ALS-01是一款数字环境光传感器(ALS),由Lite-On公司生产。printf("LTR-303ALS初始化失败!printf("LTR-303ALS初始化成功!printf("数据无效\r\n");* @param mode: 0-待机, 1-激活。

PP_Cottage的博客 1033

【光子AI 2026 企业级 Agent 架构指南】别再把 Skill 当 Tool:Agent Skills × MCP 企业级落地全指南(最新定义澄清 + 场景大全 + 选型决策树+安全工程清单)

摘要: 2026年企业级AI架构迎来两大核心标准——Agent Skills与MCP(Model Context Protocol),分别解决流程标准化与系统集成难题。Agent Skills通过“文件夹化能力包”(SOP+脚本+模板)固化专家流程,确保输出一致性;MCP则以类USB-C的协议统一外部系统接入,降低集成成本。两者差异显著:Skills专注程序性知识(如财报生成),MCP侧重动态连接(如跨平台数据调用)。实际场景中,复杂需求(如智能客服)需组合使用——MCP为骨架提供连接能力,Skills为大

AI天才研究院 2476

红黑树( 图解 + 秒懂 + 史上最全)

文章很长,建议收藏起来慢慢读!疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 经典图书:《Java高并发核心编程(卷1)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《Java高并发核心编程(卷2)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《Nett

架构师尼恩 1万+

STM32 USB键盘实现指南

在STM32上实现键盘功能可以通过USB HID(人机接口设备)协议来实现,使STM32设备能被计算机识别为标准键盘。通过上述步骤,您可以在STM32上实现一个功能完整的USB键盘。关键点包括:正确配置USB HID设备实现键盘矩阵扫描处理按键事件并生成HID报告优化按键响应和消抖处理添加额外功能如宏键和LED反馈这个实现可以作为基础,进一步扩展为游戏键盘、宏键盘或特殊输入设备。

suny8的专栏 970

浅谈算法和数据结构: 九 平衡查找树之红黑树

前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度。但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是想对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外...

weixin_34290352的博客 345

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

什么是红黑树

红黑树的英文是“Red-Black Tree”,简称 R-B Tree。它是一种不严格的平衡二叉查找树,我前面说了,它的定义是不严格符合平衡二叉查找树的定义的。那红黑树究竟是怎么定义的呢? (1)每个节点或者是黑色,或者是红色。 (2)根节点是黑色。 (3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!] (4)如果一个节点是红色的,则它的子节点必须是黑色的。 (5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。 (01) 特性(3)中的叶

鸭梨的博客 275

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

关于红黑树的介绍及实现

关于红黑树的介绍及实现 本文参考了以下博客: https://www.cnblogs.com/skywang12345/p/3245399.html https://www.cnblogs.com/skywang12345/p/3624291.html#a2 https://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html https://www.cnblogs.com/qingergege/p/7351659.html ..

krain__的博客 691

C++复习知识点

intialization list(初始化列表)-----&gt;只能一次性赋值:当类中含有const、reference成员变量时;有参构造时;基类的构造函数都需要初始化表。 assignment(分配)-----&gt;分配 c语言中的全局变量,分为初始化的(int abc=100),和未初始化的(int abcd). 初始化的全局变量,在程序加载的时候,会从程序文件中,映射(大部分操...

Wshichuan的博客 365

重温数据结构:深入理解红黑树

读完本文你将了解到: 什么是红黑树黑色高度 红黑树的 5 个特性 红黑树的左旋右旋 指定节点 x 的左旋 右图转成左图 指定节点 y 的右旋左图转成右图 红黑树的平衡插入 二叉查找树的插入 插入后调整红黑树结构 调整思想 插入染红后的调整有 2 种情况 根据 TreeMap 的代码来验证这个过程 红黑树的平衡删除 二叉查找树的删除 删除后的结构调整 调整思想 删除后的调整主要分三步 根据 TreeM

张拭心的博客 shixinzhang 3万+

红黑树的实现原理

注:本文所有内容均翻译自维基百科,部分内容为原创。 强烈建议阅读文章末尾的参考资料。 一、概述 红黑树是自平衡的二叉搜索树,是计算机科学中的一种数据结构。 平衡是指所有叶子的深度基本相同(完全相等的情况并不多见,所以只能趋向于相等) 。 二叉搜索树是指,节点最多有两个儿子,且左子树中所有节点都小于右子树。 树中节点有改动时,通过调整节点顺序(旋转),重新给节点染色,使节点满足某种特...

weixin_30376163的博客 380

浅析红黑树(RBTree)原理及实现

我们在上一篇博客认识到了平衡二叉树(AVLTree),了解到AVL树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。AVL树的效率就是高在这个地方。如果在AVL树中插入或删除节点后,使得高度之差大于1。此时,AVL树的平衡状态就被破坏,它就不再是一棵二叉树;为了让它重新维持在一个平衡状态,就需要对其进行旋转处理, 那么创建一颗平衡二叉树的成...

芮萌萌的博客 9万+

【数据结构】史上最好理解的红黑树讲解,让你彻底搞懂红黑树

狂肝半个月的学习笔记,最通俗易懂的红黑树讲解。带你快速掌握红黑树~

小七的博客 29万+
上一篇: C++漫步结构与平衡的殿堂:AVL树
下一篇: C++效率掌握之STL库:map && set底层剖析及迭代器万字详解
澪贰
澪贰 优质创作者: C/C++技术领域 优质创作者: C/C++技术领域
博客等级 码龄2年 1万+粉丝 222原创
评论 62
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值