红黑的插入

news2025/1/9 16:43:27

定义

红黑树是一种二叉搜索树
每个结点上增加一个存储位表示结点的颜色,可以是Red或Black 通过对任何一条从根到叶子的路径上各个结点着色方式的限制。

红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
红黑树是如何保证该核心属性的呢?
通过下列五个性质

性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点,即NIL节点)
    在这里插入图片描述

通过上述性质,红黑树很好的实现了没有一条路径比其他路径长两倍

没有一条路径比其他路径长两倍也可以为以下含义
红黑树中最长路径的长度不能超过最短路径的两倍
性质1,2,5是红黑树的基本性质,需要满足。没什么要讨论的。
性质3与4是解决长度问题的关键

性质3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
也可以理解为 不能出现两个连续的红节点

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

性质3与4结合来看
首先每条路径上黑节点的数目要一致,红色节点不能连着出现

当一条路径最短时,节点均为黑色;
当一条路径最长时,每个黑节点下均链接着红色节点
MAX = 2*MIN;
也就是满足了
红黑树中最长路径的长度不能超过最短路径的两倍

插入

红黑树的插入大体部分与AVL树相近,但调整时有所不同
插入的返回值时一个键值对
当插入成功时 iterator 指向插入的节点 , bool值为true
拆入失败时,即该树中已经存在该元素,iterator为原有节点,bool值为false

	std::pair<iterator,bool> Insert(const ValueType& data)
	{
		//判断是否为空树,为空树创建第一个节点
		if (_pHead == nullptr)
		{
			_pHead = new Node(data, BLACK);
			return std::make_pair(iterator(_pHead),true);
		}
		//按照二叉搜索树的规则进行插入
		//从根节点开始查找位置,根节点的父节点为nullptr
		pNode parent = nullptr;
		pNode cur = _pHead;
		//当cur指向空时,当前位置即是目标位置
		while (cur)
		{
			//parent在查询元素目标位置的过程中,
			//一定会指向cur的位置
			parent = cur;

			//二叉树具有排异性,当树中存在相同元素时,不能再插入
			if (KeyOfValue(cur->_data) == KeyOfValue(data))
			{
				return pair(cur, false);
			}
			else if (KeyOfValue(cur->_data) < KeyOfValue(data))
			{
				cur = cur->_pRight;
			}
			else
			{
				cur = cur->_pLeft;
			}
		}
		//进行元素的插入
		cur = new Node(data);
		cur->_pParent = parent;
		if (KeyOfValue(cur->_data) > KeyOfValue(parent->_data))
		{
			parent->_pRight = cur;
		}
		else
		{
			parent->_pLeft = cur;
		}
		pNode cur_copy = cur;
		//红黑树的调整
		//uncle
		// uncle = cur == parent->_pLeft ? parent->_pRight : parent->_pLeft;
		while (parent && parent->_pParent && parent->_color == RED)
		{
			pNode grand = parent->_pParent;
			//parent在左侧
			if (parent == grand->_pLeft)
			{
				pNode uncle = grand->_pRight;
				//情况二与三
				if (uncle == nullptr || uncle->_color == BLACK)
				{
					//异侧情况三
					if (cur == parent->_pRight)
					{
						RotateL(parent);
						std::swap(parent, cur);

					}
					//情况二
					RotateR(grand);
					parent->_color = BLACK;
					grand->_color = RED;
					
					if (cur == _pHead)
						cur->_color = BLACK;
					break;
				}
				//情况一
				else
				{
					uncle->_color = parent->_color = BLACK;
					//grand为根时 直接置为黑
					if (grand == _pHead)
					{
						grand->_color = BLACK;
						break;
					}
					else
					{
						grand->_color = RED;
						cur = grand;
						parent = cur->_pParent;
					}

				}
			}
			//parent在右侧
			else
			{
				pNode uncle = grand->_pLeft;
				//情况二与三
				if (uncle == nullptr || uncle->_color == BLACK)
				{
					//异侧情况三
					if (cur == parent->_pLeft)
					{
						RotateR(parent);
						std::swap(parent, cur);

					}
					//情况二

					RotateL(grand);
					parent->_color = BLACK;
					grand->_color = RED;
					
					if (cur == _pHead)
						cur->_color = BLACK;
					break;
				}
				//情况一
				else
				{
					uncle->_color = parent->_color = BLACK;
					//grand为根时 直接置为黑
					if (grand == _pHead)
					{
						grand->_color = BLACK;
						break;
					}
					else
					{
						grand->_color = RED;
						cur = grand;
						parent = cur->_pParent;
					}

				}
			}
		}
		return std::make_pair(iterator(cur_copy), true);
	}

调整

调整红黑树的前提是,插入破坏了红黑树的结构
新节点的默认颜色是红色,只有当双亲节点为红色时才破坏了红黑树的结构
当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:

红黑树的调整可以分为3中情况
以单侧举例
约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
情况一: cur为红,p为红,g为黑,u存在且为红
在这里插入图片描述
解决方式:将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑
在这里插入图片描述
说明: u的情况有两种
1.如果u节点不存在,则cur一定是新插入节点,因为如果cur不是新插入节点则cur和p一定有一个节点的颜色是黑色,就不满足性质4: 每条路径黑色节点个数相同。
2.如果u节点存在,则其一定是黑色的,那么cur节点原来的颜色一定是黑色的现在看到其是红色的原因是因为cur的子树在调整的过程中将cur节点的颜色由黑色改成红色。
解决方案
p为g的左孩子,cur为p的左孩子,则进行右单旋转
p、g变色–p变黑,g变红

情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑
在这里插入图片描述
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转。后转为情况二

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

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

相关文章

DBeaver 无法执行多行查询,报错[1064]42000

简单的两行查询&#xff0c;有分号&#xff0c;查询报错&#xff0c;无语法问题&#xff1a; 编辑连接属性&#xff1a;允许多行查询

爱校对发布全新PDF校对工具,为用户带来更为便捷的校正体验

随着数字化文档使用的普及&#xff0c;PDF格式已经成为最为广泛使用的文件格式之一。为满足广大用户对于高效、准确PDF文档校对的需求&#xff0c;爱校对团队经过深入研发&#xff0c;正式推出全新的PDF校对工具&#xff01; 这一全新工具针对PDF文件格式进行了深度优化&#…

如何在Moonriver网络上向社区代表委托投票权利

我们之前介绍了「社区代表」这一概念&#xff0c;想必大家对社区代表在治理中扮演的角色和地位有了一定的了解。 本文将介绍如何将您的投票权利委托给社区代表。请注意&#xff0c;在委托Token给社区代表这一过程中&#xff0c;并非将您的Token转移给任何人&#xff0c;而且此…

关于农林气象站的基本介绍

农林气象站可以观测各种气象参数&#xff0c;并将观测到的参数上传至农业平台&#xff0c;通过平台向人们提供数据&#xff0c;保障农作物的健康成长。 面对人口增长比例减缓、老龄化逐渐严重的现象&#xff0c;粮食生产成为人们关注的问题&#xff0c;在这种背景下&#xff0…

dll修复工具下载,msvcr120.dll丢失怎样修复

在计算机编程中&#xff0c;msvcr120.dll是一个非常重要的动态链接库文件&#xff0c;它包含了Microsoft Visual C 2010 Redistributable Package所需的运行时库。当这个文件丢失或损坏时&#xff0c;可能会导致程序无法正常运行&#xff0c;甚至出现错误提示。因此&#xff0c…

玩机搞机---安卓机型mtk和高通芯片查看分区 导出分区 备份分区的一些工具分析

前面分享过几期mtk和高通芯片机型对于备份系统 备份分区的一些博文。很多友友比较感兴趣&#xff0c;尤其是有些专门从事小众机型定制修改系统的朋友和其他从事安卓芯片类机型的玩家。因为其有些安卓设备各种途径无法获取到出厂系统。那么从当前机型备份系统和分区是有一定必要…

当一个程序员决定穿上粉裤子

作为一个大众眼中的“非典型程序员”&#xff0c;我喜欢拥抱时尚和潮流&#xff0c;比如我经常在演讲时穿粉色裤子&#xff0c;这甚至已经成为一个标志性打扮。某天又逢主题演讲日&#xff0c;我站在衣柜前挑选上衣的时候&#xff0c;忽然灵光乍现&#xff1a;有没有可能借助 M…

Windows10批处理命令行设置环境变量笔记,无需重新安装python与chrome

近期&#xff0c;工作中经常安装、部署python生产、开发环境&#xff0c;比较麻烦&#xff0c;也没有心情去优化。突然&#xff0c;我的电脑崩溃了&#xff0c;在重新安装电脑的过程中&#xff0c;保留了原来的安装软件&#xff08;有的没有放在系统盘中&#xff09;&#xff0…

DETRs with Collaborative Hybrid Assignments Training论文笔记

Title&#xff1a;[DETRs with Collaborative Hybrid Assignments Training Code 文章目录 1. Motivation2. one to one VS one to many3. Method&#xff08;1&#xff09;Encoder feature learning&#xff08;2&#xff09;Decoder attention learning 1. Motivation 当前…

关于异数OS服务器CPU效能分析工具

该工具发布背景 近年来&#xff0c;国产服务器CPU产业的逐渐发展&#xff0c;但由于专业性较差&#xff0c;与国外存在40年以上技术差距&#xff0c;一些服务器CPU厂商利用信息差来制造一些非专业的数据夸大并虚假宣传混淆视听&#xff0c;成功达到劣币驱良币的目标&#xff0…

关于vCenter 503报错

现象&#xff1a; 打开我们的服务器界面&#xff08;虚拟机&#xff09;报错&#xff1a; 503 服务器问题 当前服务不可用。web服务器不能处理HTTP请求&#xff0c;可能是临时超载或者是服务器进行停机维护。 错误提示是由 VMware vCenter Server&#xff08;vCen…

Java学习笔记——继承(包括this,super的使用总结)

继承&#xff1a; 使用情景&#xff1a;当类与类之间&#xff0c;存在相同&#xff08;共性&#xff09;的内容&#xff0c;并满足子类是父类的一种&#xff0c;就可以考虑使用继承&#xff0c;来优化代码 Java中提供一个关键字extends&#xff0c;用这个关键字&#xff0c;我…

requests模板成功下载,但是不能在pycharm中运行

在做实验的过程中&#xff0c;需要用到requests&#xff0c;但是在pycharm中成功下载&#xff0c;仍然无法使用&#xff0c;找了很久&#xff0c;解决方法如下&#xff1a; 进入win中的命令提示符 下载requests模块 pip install requests输入python显示你的python的基本信息&…

《动手学深度学习》-21卷积层里的多输入多输出通道

沐神版《动手学深度学习》学习笔记&#xff0c;记录学习过程&#xff0c;详细的内容请大家购买书籍查阅。 b站视频链接 开源教程链接 卷积层里的多输入多输出通道 大家通常最在意的一个超参数&#xff1a; RGB图像不仅仅是单纯的矩阵&#xff0c;是3 x h x w的形状&#xf…

基于Python的图像信息隐藏技术的设计与实现

博主介绍&#xff1a;✌csdn特邀作者、博客专家、java领域优质创作者、博客之星&#xff0c;擅长Java、微信小程序、Python、Android等技术&#xff0c;专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推…

使用高斯滤波器进行表面开放轮廓过滤研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

『已解决』VMware 打开运行一段时间后卡死,CPU占比增至100%

&#x1f4e3;读完这篇文章里你能收获到 通过图文方式解决VMware 打开运行一段时间后卡死&#xff0c;CPU占比增至100%的问题 文章目录 一、系统环境二、问题描述三、解决办法1. 检查Hyper-V没有开启2. 禁止HV主机服务3. 设置Hyper-V服务为关闭状态4. 重启电脑 一、系统环境 …

开源跨境电商ERP的优缺点分析,你知道几个?

作为电子商务领域的专家&#xff0c;我们不得不关注开源跨境电商ERP的崛起。在这篇文章中&#xff0c;我们将深入探讨开源跨境电商ERP的优点和缺点&#xff0c;帮助您更好地了解这一新兴技术的潜力与挑战。 1. 开源跨境电商ERP的优点 开源跨境电商ERP相较于传统的商业ERP系统…

概念解析 | 全极化雷达成像

注1&#xff1a;本文系“概念解析”系列之一&#xff0c;致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是&#xff1a;全极化雷达成像。 全极化雷达成像** 高分辨全极化昆虫雷达极化校准与昆虫体轴方向估计 一、背景介绍 雷达是20世纪的一项伟大发明&#xff0…

pip安装torch_scatter, torch_sparse报错

在安装torch_geometric时还需要安装torch_scatter和torch_sparse&#xff0c;但是直接使用pip install安装会报错&#xff0c;报错内容是缺乏依赖项。查了好久发现直接下载whl到本地再使用pip安装时最不容易出错的&#xff0c;这里记录一下&#xff0c;避免再次掉坑。 首先需要…