红黑树的旋转

news2024/12/23 11:04:09

红黑树的基本性质

红黑树与普通的二叉搜索树不同,它在每个节点上附加了一个额外的属性——颜色,该颜色可以是红色黑色。通过引入这些颜色,红黑树能够维持以下 5 个基本性质,以确保树的平衡性:

  1. 每个节点是红色或黑色
  2. 根节点是黑色
  3. 所有叶子节点(NIL 节点)是黑色
  4. 如果一个节点是红色的,那么它的两个子节点都是黑色的(即,红色节点不能有红色子节点)。
  5. 从任一节点到其每个叶子节点的所有路径上都包含相同数量的黑色节点

 红黑树节点结构

template<class K>
struct RBtree_Node
{
	RBtree_Node<K>* _parent;
	RBtree_Node<K>* _right;
	RBtree_Node<K>* _left;

	color _color;
	K _value;

	RBtree_Node(const K& value)
		:_parent(nullptr)
		,_right(nullptr)
		,left(nullptr)
		,_color(RED)
		,_value(value)
	{}

};

红黑树与AVL树不同使用 颜色作为判断旋转或者变色的条件,也就是 红色节点的子节点不能为红色 ,每一条路径上黑色节点个数相同(这个大家刚开始看可能不理解怎么保持,每一条路径上黑色节点个数相同,没事,往下看),我们可以使用 枚举类型将我们需要的颜色封装起来,这里的颜色就是一个标识符,我们使用符号,或者是任意数字都是可以的

enum color
{
	RED,
	BACK
};

 红黑树的旋转变色

变色

uncle节点存在并为红色

这里的cur节点一定是新插入的节点,这里的cur无论是作为parent的左节点还是右节点都是无所谓的, 因为并不存在旋转问题,我们只需要遵循好红黑树的性质规则,更新节点颜色即可,同时更新parent节点和cur节点,因为pparent节点颜色改变了,我们就可以把pparent节点红色节点作为新插入节点进行上层树的更新,保持红黑树性质

if (uncle && uncle->_colour == RED)
{
	//更换颜色
	parent->_colour = uncle->_colour = BLACK;
	grandfather->_colour = RED;
    
    //更新节点
    cur = grandfather;
	parent = cur->_parent;
}

 旋转变色(单方向的节点)

 uncle存在但为黑色

 cur可以作为插入节点,也可能是因为插入而导致自己从黑色变成的红色,他的子节点一定为黑色(我们可以参考上面变色的情况),所以并不违反所有路径上黑色节点数量相等的情况,这也就是黑色节点怎么往下更新变多,同时路径上黑色节点数量相等的原因!

uncle不存在

 ​​​​​​

因为没有uncle节点,所以cur节点一定是新插入的 (如果不是新插入的,其子节点一定存在黑黑色节点,但是右树并没有额外的黑色节点,这样每一条路径上的黑色节点并不相同),类似于AVL树旋转一下

  旋转变色(变折的节点)

 uncle存在但为黑色

 只是将变折的节点方向改成单向的,没有其他特色,甚至方向反转一下就是右左情况的

 uncle不存在

我在这里列举不同情况的两个方向的反折,都是一样的 

 具体代码

循环条件及变色
while (parent && parent->_colour == RED)
{

	//      g
	//   p     u
	//c
	Node* grandfather = parent->_parent;
	if (parent == grandfather->_left)
	{
		Node* uncle = grandfather->_right;

		if (uncle && uncle->_colour == RED)
		{
			//更换颜色
			parent->_colour = uncle->_colour = BLACK;
			grandfather->_colour = RED;

			cur = grandfather;
			parent = cur->_parent;
		}
		else
		{
			//单旋
			//       g
			//    p
			// c

			//双旋
			//       g
			//    p
			//       c
			if (cur == parent->_left)
			{
				RotateR(grandfather);
				grandfather->_colour = RED;
				parent->_colour = BLACK;
			}
			else
			{
				RotateL(parent);
				RotateR(grandfather);
				grandfather->_colour = RED;
				cur->_colour = BLACK;
			}


			break;

		}
	}
	else
	{
		Node* uncle = grandfather->_left;

		if (uncle && uncle->_colour == RED)
		{
			//更换颜色
			parent->_colour = uncle->_colour = BLACK;
			grandfather->_colour = RED;

			cur = grandfather;
			parent = cur->_parent;
		}
		else
		{
			//单旋
			//  g
			//     p
			//        c

			//双旋
			// g
			//    p
			// c
			if (cur == parent->_right)
			{
				RotateL(grandfather);
				grandfather->_colour = RED;
				parent->_colour = BLACK;
			}
			else
			{
				RotateR(parent);
				RotateL(grandfather);
				grandfather->_colour = RED;
				cur->_colour = BLACK;
			}

			break;

		}
	}

}
终止代码解释
while (parent && parent->_colour == RED)

为什么如果parent是红色节点就要继续呢,或者旋转变色后就可以退出?

在变色情况下 cur还是红色,他的parent如果还是红色,不满足性质4 需要继续变色,或者旋转变色,同理在旋转变色情况下,cur变成了黑色 ,这时候cur的parent无论是什么颜色都不会影响,同时,每一条路径上的黑色节点没有变换,符合所有性质

左右旋转函数代码 
void RotateL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;

	parent->_right = subRL;
	if (subRL) subRL->_parent = parent;

	subR->_left = parent;
	Node* Parent = parent->_parent;
	parent->_parent = subR;
	subR->_parent = Parent;

	if (Parent == nullptr)
	{
		_root = subR;
	}
	else
	{
		if (Parent->_left == parent)
		{
			Parent->_left = subR;
		}
		else
		{
			Parent->_right = subR;
		}
	}

}

void RotateR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;

	parent->_left = subLR;
	if (subLR) subLR->_parent = parent;

	subL->_right = parent;
	Node* Parent = parent->_parent;
	parent->_parent = subL;
	subL->_parent = Parent;

	if (Parent == nullptr)
	{
		_root = subL;
	}
	else
	{
		if (Parent->_left == parent)
		{
			Parent->_left = subL;
		}
		else
		{
			Parent->_right = subL;
		}
	}
}

红黑树与AVL树的区别

红黑树和AVL树都是自平衡二叉搜索树,它们的主要目的是通过保持树的平衡来优化查找、插入和删除操作的时间复杂度。

为什么需要自平衡搜索树呢?

如果我们一直在二叉树中输入较大的值,我们会发现,树慢慢成为了链表,远远没有达到我们想要的搜索时间复杂度O(logn)

红黑树与AVL树的区别

AVL树严格的控制树左右高度差小于2,也就是严格保持搜索树处于接近于满二叉树的情况,使时间复杂度极限接近于O(logn),但是这样会导致插入时,树的旋转开销较大,但是红黑树,保持树的黑色节点相同,在保持树的高度差的同时,减少了旋转的情况,

 可以总结为:

  • 红黑树适合频繁插入和删除的场景,因其在操作过程中旋转次数少,性能较为稳定。
  • AVL树则更适合查找频繁、插入删除较少的场景,提供了更好的查找性能,但在频繁更新时旋转次数较多,性能较低。

C++库函数中 map set也是使用红黑树实现的 ,我们也开始将自己写的红黑树封装出 自己的map set

ps:具体代码可见:study/c++_study/RBtree/RBtree/RBtree.h at main · zjsnh/study (github.com)

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

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

相关文章

C++入门10——stack与queue的使用

目录 1.什么是stack&#xff1f; stack的使用 2.什么是queue&#xff1f; queue的使用 3.priority_queue 3.1 什么是priority_queue? 3.2 priority_queue的使用 1.什么是stack&#xff1f; 在官网中&#xff0c;对stack有这样的介绍&#xff1a; Stacks are a type o…

一台电脑对应一个IP地址吗?‌探讨两台电脑共用IP的可能性

在当今数字化时代&#xff0c;‌IP地址作为网络世界中的“门牌号”&#xff0c;‌扮演着至关重要的角色。‌它负责在网络上唯一标识每一台设备&#xff0c;‌使得数据能够在庞大的互联网中准确无误地传输。‌然而&#xff0c;‌对于IP地址与电脑之间的对应关系&#xff0c;‌许…

uni-appH5项目实现导航区域与内容区域联动效果

一、需求描述 将导航区域与内容区域实现联动&#xff0c;即点击导航区域&#xff0c;内容区滚动到对应位置&#xff0c;内容区滚动过程中根据内容定位到相对应的导航栏。 效果如下&#xff1a; 侧边导航与内容联动效果 二、功能实现思路分析汇总&#xff1a; 三、具体代码 1…

Matplotlib通过axis()配置坐标轴数据详解

坐标轴范围设置 axis()可以直接传入列表[xmin,xmax,ymin,ymax]进行范围设置, 分别可以使用plt.axis()或者画布对象.axis()进行配置 import numpy as np import matplotlib.pyplot as pltx np.linspace(0, 20, 100) y x*2 plt.plot(x, y, r) plt.axis([0,30,0,100]) plt.sa…

【精选】文件摆渡系统:跨网文件传输的安全与效率之选

文件摆渡系统可以解决哪些问题&#xff1f; 文件摆渡系统&#xff08;File Shuttle System&#xff09;主要是应用于不同网络、网段、区域之间的文件数据传输流转场景&#xff0c; 用于解决以下几类问题&#xff1a; 文件传输问题&#xff1a; 大文件传输&#xff1a;系统可…

云服务器内网穿透连接云手机配置ALAS

文章目录 服务器安装TailscaleNAT网络&#xff08;无独立IP&#xff09;云服务器安装Tailscale有固定IP的云服务器安装Tailscale 云手机安装Tailscale开启无线网络调试安装Tailscale ALAS连接云手机 上次写到服务器连接云手机时只说了有独立IP的&#xff0c;但有独立IP的云手机…

IDM 工具下载 地图高程数据

巧用IDM工具 快捷下载ASTER GDEM v3高程数据 ASTER GDEM v3是NASA推出的30米高清DEM,覆盖了几乎全部的地球陆地。那么,在NASA官网怎么下载ASTER GDEM v3的地形高程数据呢? 首先,你需要注册一个nasa的账号 注册网址: https://urs.earthdata.nasa.gov/users/new 注册方式和国…

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它&#xff1f;电脑屏保多样化&#xff0c;让大家有了更多的选择&#xff0c;让更多人有机会把自己的电脑打扮得漂漂亮亮&#xff0c;今天小编给大家推荐&#xff1a;芝麻时钟&#xff08;官网下载地址&#xff1a;http…

vulhub GhostScript 沙箱绕过(CVE-2018-16509)

1.执行以下命令启动靶场环境并在浏览器访问 cd vulhub/ghostscript/CVE-2018-16509 #进入漏洞环境所在目录 docker-compose up -d #启动靶场 docker ps #查看容器信息 2.访问网页 3.下载包含payload的png文件 vulhub/ghostscript/CVE-2018-16509/poc.png at master vulh…

TYPE-C USB设计

目录 摘要 TYPE-C电路 握手过程 USB电路 摘要 TYPE-C,是USB的一种接口&#xff0c;USB的第一种接口为常见的USB接口&#xff0c;U盘即为这种接口&#xff1b;第二种接口的形状类似一个凸字&#xff0c;常应用在打印机中&#xff0c;第三种接口即为TYPE-C&#xff0c;支持正…

JdbcRowSetImpl利用链分析

文章目录 JdbcRowSetImpl利用链前言JdbcRowSetImpl利用链分析 JdbcRowSetImpl利用链 前言 首先说明一下&#xff1a;利用链都有自己的使用场景&#xff0c;要根据场景进行选择不同的利用链。 JdbcRowSetImpl利用链用于fastjson反序列化漏洞中。 为什么&#xff1f; 因为fa…

暑期档总结:哪部国漫年番表现更优?

“暑期档”可能是所有档期中绵延时间最长的&#xff0c;作为该时间段主力的学生人群&#xff0c;在学业压力较小的假期中&#xff0c;需要更多娱乐方式来填充生活。除了电影之外&#xff0c;动画番剧越来越成为这一群体的不二选择&#xff0c;各个动画制作公司也会选择把精彩剧…

html记账本改写:数据重新布局,更好用了,没有localStorage保存版本

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>htm记账本</title><style>table {user-select: none;/* width: 100%; */border-collapse: collapse;}table,th,td {border: 1px solid …

RISC-V架构下 DSA - AI算力的更多可能性:Banana Pi BPI-F3 进迭时空

AI已经从技术走向应用&#xff0c;改变了我们的生活和工作方式。近些年&#xff0c;AI算力芯片领域群雄逐鹿&#xff0c;通过对芯片、算力与AI三者发展迭代过程的理解&#xff0c;我们发现高能效比的算力、通用的软件栈以及高度优化的编译器&#xff0c;是我们的AI算力产品迈向…

稚晖君同款 clion嵌入式开发环境搭建

前言 前段时间看到稚晖君的单片机开发环境&#xff0c;感觉挺酷的&#xff0c;自己也想尝试下&#xff0c;这里记录下安装过程。 安装文件准备 stm32cubemx安装 stm32cubemx stm32cubemx下载地址 当前时间是2024年9月4日&#xff0c;下载的版本是6.12.0版本&#xff0c;下…

一、关系模型和关系代数,《数据库系统概念》,原书第7版

文章目录 [toc]一、引言1.1 什么是数据库1.2 数据完整性1.3 数据库的操作1.4 数据库的持久性1.5 数据库管理系统1.6 数据模型1.7 早期DBMS 二、关系模型2.1 什么是关系模型2.2 关系数据库的结构2.3 键2.4 约束2.5 数据操纵语言(DML)2.6 关系代数2.6.1 选择运算2.6.2 投影运算2.…

【南方科技大学】CS315 Computer Security 【Lab1 Packet Sniffing and Wireshark】

目录 IntroductionBackgroundTCP/IP Network StackApplication LayerTransport LayerInternet LayerLink LayerPacket Sniffer Getting WiresharkStarting WiresharkCapturing PacketsTest Run Questions for the Lab Introduction 实验的第一部分介绍数据包嗅探器 Wireshark。…

2024高教社杯全国大学生数学建模竞赛B题原创python代码

以下均为python代码。先给大家看看之前文章的部分思路&#xff1a; 接下来我们将按照题目总体分析-背景分析-各小问分析的形式来 1 总体分析 题目提供了一个电子产品生产的案例&#xff0c;要求参赛者建立数学模型解决企业在生产过程中的一系列决策问题。以下是对题目的总体…

Cortex-A7:简单中断处理(不可嵌套中断)机制

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf ARM体系结构与编程第2版1 前言 Cortex-M系列内核MCU中断硬件原生支持嵌套中断&#xff0c;开发者不需要为了实现嵌套中断而进行额外的工作。但在Cortex-A7中&#xff0c;硬件原生是不支持嵌套中断的&#xff0c;这从Cortex-A…

隐私计算实训营:联邦学习在垂直场景的开发实践

纵向联邦学习 纵向联邦学习的参与方拥有相同样本空间、不同特征空间的数据&#xff0c;通过共有样本数据进行安全联合建模&#xff0c;在金融、广告等领域拥有广泛的应用场景。和横向联邦学习相比&#xff0c;纵向联邦学习的参与方之间需要协同完成数据求交集、模型联合训练和…