C++--红黑树

news2025/1/20 10:52:41

1.什么是红黑树

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

 性质:

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

注意:黑色节点相同,红色节点不连续,所以最长路径中节点个数不会超过最短路径节点个数的两倍。

2.红黑树的插入实现

由于红黑树是一颗二叉平衡搜索树,所以它的性质和AVL树差不多(AVL树的特性:左右子树高度差的绝对值不超过一)。

红黑树的插入可以分为两部分:按照二叉搜索树的规则插入新节点,然后判断是否需要旋转交换和改变颜色。

检测新节点的插入,需要判断是否破坏了红黑树的性质,因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论。

插入代码的实现:

#pragma once
using namespace std;
#include <assert.h>
namespace sss
{
	enum Color
	{
		 red,
		black
	};
	template<class K,class V>
	struct RedBlackTreeNode
	{
		RedBlackTreeNode<K,V>* _left;
		RedBlackTreeNode<K, V>* _right;
		RedBlackTreeNode<K, V>* _parent;
		pair<K, V> _date;
		Color _col;
		

		RedBlackTreeNode(const pair<K, V>& date=make_pair(0,0))
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_date(date)
			//, _col(black)
		{}

	};
	template<class K, class V>
	class RedBlackTree
	{
		typedef RedBlackTreeNode<K, V> Node;
	public:
		typedef RedBlackTree Tree;
		bool insert(const pair<K, V>& date)
		{
			if (_root == nullptr)
			{
				_root = new Node(date);
				_root->_col = black;
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_date< date)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (cur->_date> date)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(date);
			cur->_col = red;
			if (parent->_date.first < date. first)
			{
				parent->_right = cur;
			}
			else 
			{
				parent->_left = cur;
			}
			cur->_parent = parent;
			//Node* uncle=parent->_parent->
			while (parent && parent->_col == red)
			{
				Node* grandfater = parent->_parent;
				assert(grandfater);
				assert(grandfater->_col==black);
				if (parent == grandfater->_left)
				{
					Node* uncle = grandfater->_right;
					// 情况一 : uncle存在且为红,变色+继续往上处理
					if (uncle && uncle->_col == red)
					{
						parent->_col = uncle->_col = black;
						grandfater->_col = red;
						// 继续往上处理
						cur = grandfater;
						parent = cur->_parent;
					}// 情况二+三:uncle不存在 + 存在且为黑
					else
					{
						// 情况二:右单旋+变色
						//     g 
						//   p   u
						// c

						if (cur == parent->_left)
						{
							RotateR(grandfater);
							parent->_col = black;
							grandfater->_col = red;
						}
						else
						{
							// 情况三:左右单旋+变色
							//     g 
							//   p   u
							//     c
							RotateL(parent);
							RotateR(grandfater);
							cur->_col = black;
							grandfater->_col = red;
						}
						break;

					}
				}
				else
				{
					Node* uncle = grandfater->_left;
					// 情况一
					if (uncle && uncle->_col == red)
					{
						parent->_col = uncle->_col = black;
						grandfater->_col = red;
						// 继续往上处理
						cur = grandfater;
						parent = cur->_parent;
					}
					else
					{
						// 情况二:左单旋+变色
						//     g 
						//   u   p
						//         c
						if (cur == parent->_right)
						{
							RotateL(grandfater);
							parent->_col = black;
							grandfater->_col = red;
						}
						else
						{
							// 情况三:右左单旋+变色
							//     g 
							//   u   p
							//     c
							RotateR(parent);
							RotateL(grandfater);
							cur->_col = black;
							grandfater->_col = red;
						}

						break;
					}
				}
			}
			_root->_col = black;
			return true;
		}
		void Inorder()
		{
			_Inorder(_root);
		}
	private:
		//右旋
		void RotateR(Node* parent)
		{
			Node* subl = parent->_left;
			Node* sublr = subl->_right;
			Node* prev = parent->_parent;
			parent->_left = sublr;
			if (sublr)
				sublr->_parent = parent;
			parent->_parent = subl;
			subl->_right = parent;
			if (_root == parent)
			{
				_root = subl;
				subl->_parent = nullptr;
			}
			else
			{
				if (prev->_left == parent)
				{
					subl->_parent = prev;
					prev->_left = subl;
				}
				else
				{
					subl->_parent = prev;
					prev->_right = subl;
				}
			}
		}
		//左旋
		void RotateL(Node* parent)
		{
			Node* subr = parent->_right;
			Node* subrl = subr->_left;
			Node* prev = parent->_parent;

			parent->_right = subrl;
			if (subrl)
				subrl->_parent = parent;
			subr->_left = parent;
			parent->_parent = subr;
			if (_root == parent)
			{
				_root = subr;
				subr->_parent = nullptr;
			}
			else
			{
				if (prev->_left == parent)
				{
					subr->_parent = prev;
					prev->_left = subr;
				}
				else
				{
					subr->_parent = prev;
					prev->_right = subr;
				}
			}
		}
		void _Inorder(Node* _root)
		{
			if (_root == nullptr)
				return;
			_Inorder(_root->_left);
			cout << _root->_date.first << " " << _root->_date.second << endl;
			_Inorder(_root->_right);
		}
	private:
		Node* _root = nullptr;
	};

}


 

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

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

相关文章

java.net.BindException Address already in use: NET_Bind解决

java.net.BindException Address already in use: NET_Bind 两种解决方法 两种解决方法 (1) kill 占用此端口的线程 查看报错的端口 netstat -ano | findstr 16825tasklist | findstr 1092 如果占用的程序不重要直接kill taskkill /f /pid 16825 (2) 修改启动端口 找一个没…

系统架构设计师-信息安全技术(2)

目录 一、安全架构概述 1、信息安全所面临的威胁 二、安全模型 1、安全模型的分类 2、BLP模型 3、Biba 模型 4、Chinese Wall模型 三、信息安全整体架构设计 1、WPDRRC模型 2、各模型的安全防范功能 四、网络安全体系架构设计 1、开放系统互联安全体系结构 2、安全服务与安…

typedef

t y p e d e f typedef typedef 声明&#xff0c;简称typedef&#xff0c;是创建现有类型的新名字。 比如&#xff1a; #include <bits/stdc.h> using namespace std; typedef long long ll; int main() {ll n;scanf("%lld",&n);printf("%lld"…

共定位数据和环境准备

共定位数据和环境准备 一、数据准备 如果需要做eqtl-GWAS的共定位&#xff0c;则需要按照药靶教程中&#xff0c;将eqtl数据放在smr目录内 如果是纯GWAS-GWAS的共定位&#xff0c;涉及到本地数据的&#xff0c;需要将其整理成模板SNP的格式&#xff0c;并且需要chr&#xff0c…

CASAIM与哈尔滨工业大学达成航空航天关键零部件自动化智能测量系统合作,助力航空航天特种复合新材料性能分析

近期&#xff0c;CASAIM与哈尔滨工业大学在航空航天关键零部件自动化智能测量系统展开全面合作&#xff0c;为后续进行航空航天特种复合新材料性能分析提供可靠的试验数据。 哈尔滨工业大学是隶属于工业和信息化部的全国重点大学&#xff0c;是国家“985工程”“211工程”“双…

【Ubuntu】从Graylog到Grafana Loki:构建更强大的网络设备管理和监控系统

在将Graylog部署到生产环境时&#xff0c;我们遇到了一些问题&#xff0c;其中最主要的是无法安装MongoDB并且无法随时重启机器去修改BIOS设置来修复问题 【WARNING: MongoDB 5.0 requires a CPU with AVX support, and your current system does not appear to have that! 】。…

云服务 Ubuntu 20.04 版本 使用 Nginx 配置SSL证书和nginx从HTTP跳转到HTTPS

1.云服务申请免费的SSL证书 2.从云服务SSL证书下载到本地解压上传到服务器 3.配置Nginx下的 nginx.cof 文件 4.开放安全组&#xff0c;内部与外部 5.测试配置与跳转是否成功 1.云服务申请免费的SSL证书 1.1.登录云平台找到SSL证书 注意&#xff1a;博主这里是腾讯云&#x…

程序员如何利用公网远程访问查询本地硬盘【内网穿透】

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《高效编程技巧》《cpolar》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 公网远程访问本地硬盘文件【内网穿透】 文章目录 公网远程访问本地硬盘文件【内网穿透】前言1. 下载cpolar和Everything软件1.…

OJ练习第151题——克隆图

克隆图 力扣链接&#xff1a;133. 克隆图 题目描述 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08;克隆&#xff09;。 示例 分析 对于一张图而言&#xff0c;它的深拷贝即构建一张与原图结构&#xff0c;值均一样的图&#xff0c;但是…

光伏发电系统的并网接入点选择及接入方案

1.并网方式及接入点选择 (1))并网点与接入点定义 1)并网点。对于有升压站的分布式电源&#xff0c;并网点为分布式电源升压站中压侧母线或节点&#xff0c;对于无升压站的分布式电源&#xff0c;并网点为分布式电源的输出汇总点。图1中所示A1、B1点分别为分布式电源A、B的并网…

工业视觉相机镜头选型方法

一、相机选型 1、首先&#xff0c;根据检测需求确定选用黑白/彩色、面阵/线阵相机&#xff0c;接口类型一般选择GigE 2、确定检测精度要求&#xff08;最小特征尺寸mm&#xff09;、视野范围&#xff0c;一个测量精度对应几个像素数&#xff08;一般取3-5&#xff09; 3、计…

【山河送书第七期】:《强化学习:原理与Python实战》揭秘大模型核心技术RLHF!

《强化学习&#xff1a;原理与Python实战》揭秘大模型核心技术RLHF&#xff01; 一图书简介二RLHF是什么&#xff1f;三RLHF适用于哪些任务&#xff1f;四RLHF和其他构造奖励模型的方法相比有何优劣&#xff1f;五什么样的人类反馈才是好反馈&#xff1f;六如何减小人类反馈带来…

Matplotlib数据可视化(四)

1.在绘图中显示公式 在Matplotlib中可以使用LaTex的命令来编辑公式&#xff0c;只需要在字符串前面加一个r即可。 示例1&#xff1a; import numpy as np import matplotlib.pyplot as plt plt.xlim([1,4]) plt.ylim([1,3]) plt.text(2,2,r$ \alpha \beta \pi \lambda \omeg…

新榜 | CityWalk本地生活商业价值洞察报告

如果说现在有人问&#xff0c;最新的网络热词是什么? “CityWalk”&#xff0c;这可能是大多数人的答案。 近段时间&#xff0c;“CityWalk”刷屏了各种社交媒体&#xff0c;给网友们带来了一场“城市漫步”之旅。 脱离群体狂欢&#xff0c;这个在社交媒体引发热议的词汇背后又…

【leetcode】232. 用栈实现队列

1.使用两个栈结构构建队列 我们需要自定义栈及其相关操作 栈结构遵循后入先出的原则&#xff0c;队列结构遵循先入先出的原则 构建具有两个栈结构的队列&#xff0c;栈pushST用于数据的插入&#xff0c;栈popST用于数据的删除 为栈结构动态开辟空间并初始化栈结构 //定义一个具…

object获取的两种方式/Object.keys使用/解构赋值

object获取的两种方式&#xff1a; data() {return {abj: {aa: {A: 1}}}},created() {console.log(this.abj.aa) //第一种console.log(this.abj["aa"]) //第二种}, Object.keys使用/解构赋值&#xff1a; return {footList: [],abj: {aa: {A: 12,AA:22},bb: {…

macOS系统安装python3

官网下载 官网&#xff1a;https://www.python.org/ 选择最新版本下载 双击安装包 点击继续 点击继续 点击同意 点击安装 终端执行 python3 --version

九、Linux下,如何在命令行进入文本编辑页面?

1、文本编辑基础 说到文本编辑页面&#xff0c;那就必须提到vi和vim&#xff0c;两者都是Linux系统中&#xff0c;常用的文本编辑器 2、三种工作模式 3、使用方法 &#xff08;1&#xff09;在进入Linux系统&#xff0c;在输入vim text.txt之后&#xff0c;会进入文本编辑中&…

【JS】for 与 forEach 分别如何跳出循环

for 循环 在 for 循环中&#xff0c;退出循环的两种方式&#xff1a; break; 退出整个循环continue; 退出当次循环 let array [1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let i 0; i < array.length; i) {if (array[i] 6) {// break; // 退出整改循环&#xff0c;continue; /…

高并发内存池(centralcache)[2]

Central cache threadcache是每个线程独享&#xff0c;而centralcache是多线程共享&#xff0c;需要加锁&#xff08;桶锁&#xff09;一个桶一个锁 解决外碎片问题&#xff1a;内碎片&#xff1a;申请大小超过实际大小&#xff1b;外碎片&#xff1a;空间碎片不连续&#x…