c++红黑树,插入公式

news2024/9/22 1:45:27

概念


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

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

 

插入

其实对于红黑树来说其实就是维护好一个规则,我们插入的时候每次除了第一个节点是插入节点是黑色,以后插入的新节点都是红色,插入完我们再判断是否需要去修改颜色,和旋转。修改颜色和旋转也是有公式的。

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

情况一

每次当我们修改完颜色之后还需要向上循环去继续修改。
 

情况二

cur为红,p为红,g为黑,u不存在/u存在且为黑

情况三

其实就是需要双旋的情况

代码:
 

	bool insert(const K&key,const V&value)
	{
		if (_node == nullptr)
		{
			_node = new rbtreeNode(make_pair(key, value));
			_node->_col = BLACK;
			return true;
		}
		rbtreeNode* root = _node;
		rbtreeNode* rootp = _node;
		while (root)
		{
			if (key < root->_kv.first)
			{
				rootp = root;
				root = root->_left;
			}
			else if(key>root->_kv.first)
			{
				rootp = root;
				root = root->_right;
			}
			else
			{
				break;
			}
		
		}

		rbtreeNode* newnode = new rbtreeNode(make_pair(key,value));
		if (key < rootp->_kv.first)
		{
			rootp->_left = newnode;
		}
		else
		{
			rootp->_right = newnode;
		}
		newnode->_parent = rootp;
		newnode->_col = RED;
		rbtreeNode* cur = newnode;
		while (rootp&&rootp->_col==RED)
		{

			rbtreeNode* grandfather = rootp->_parent;
			if (grandfather->_left == rootp)// u存在且为红 -》变色再继续往上处理
			{
				rbtreeNode* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					uncle->_col = rootp->_col = BLACK;
					grandfather->_col = RED;
					cur = rootp;
					rootp = rootp->_parent;
					if (rootp == _node)
						break;
				}
				else
				{
					if (rootp->_left == cur)
					{
                        //    g
						//  p   u
						//c
						//单旋
						rotateR(grandfather);
						rootp->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						//  p   u
						//    c
						//双旋
						rotateL(rootp);
						rotateR(grandfather);
						grandfather->_col = RED;
						cur->_col = BLACK;
					}
					break;
				}
			}
			else
			{
				rbtreeNode* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					uncle->_col = rootp->_col = BLACK;
					grandfather->_col = RED;
					cur = rootp;
					rootp = rootp->_parent;
					if (rootp == _node)
						break;
				}
				else 
				{
					if (rootp->_right == rootp)
					{
						rotateL(grandfather);
						grandfather->_col = RED;
						rootp->_col = BLACK;
					}
					else
					{
						rotateR(rootp);
						rotateL(grandfather);
						grandfather->_col = RED;
						cur->_col = BLACK;
					}
					break;
				}
			}
		}
		_node->_col = BLACK;
		return true;

	}

红黑树的验证

这里我们也是去写一个函数去判断是否为红黑树。

bool isrbtree()
{
	return isrbtree(_node);    //将判断函数封装起来
}

bool isrbtree(rbtreeNode*root)
{
	if (root == nullptr)
	{
		return true;
	}
	int size = 0;
	rbtreeNode* head = root;
	while (head)
	{
		if (head->_col == BLACK)
			size++;
		head = head->_left;       //找一个节点有多少个黑色节点,每条路径都有相同的黑色节点
	}

	if (_node->_col == RED)
	{
		cout << "根为红" << endl;    //如果根节点吗为红色return false
		return false;
	}

	return  iscout(root,0,size);

}

bool iscout(rbtreeNode*root,int count,int N)
{
	if (root == nullptr)
	{
		if (count == N)			//判断每条路径的高是否相同。
			return true;
		else
		{
			cout << count << " " << N << endl;
			cout << "高不同" << endl;
			return false;
		}
	}
	
	if (root->_col==BLACK)
	{
		count++;
	}

	rbtreeNode* rootp = root->_parent;
	if (rootp&&rootp->_col==RED&&root->_col==RED)
	{
		cout << "有在一起的红节点" << endl;  //判断是否有连在一起的红节点
		return false;
	}
	return iscout(root->_left, count, N) && iscout(root->_right, count, N);
}

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

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

相关文章

useRoute 函数的详细介绍与使用示例

title: useRoute 函数的详细介绍与使用示例 date: 2024/7/27 updated: 2024/7/27 author: cmdragon excerpt: 摘要&#xff1a;本文介绍了Nuxt.js中useRoute函数的详细用途与示例&#xff0c;展示了如何在组合式API中使用useRoute获取当前路由信息&#xff0c;包括动态参数、…

web服务器dns服务器配置服务

1.搭建一个nfs服务器&#xff0c;客户端可以从该服务器的/share目录上传并下载文件 server服务器&#xff1a; 创建 /share目录&#xff0c;并且编辑/etc/exports文件 更改目录权限为755&#xff1a; 755权限码的含义是&#xff1a; 文件所有者&#xff08;第一位数字7&…

Docker Desktop安装(通俗易懂)

1、官网 https://www.docker.com/products/docker-desktop/ 2、阿里云镜像 docker-toolbox-windows-docker-for-windows安装包下载_开源镜像站-阿里云 1. 双击安装文件勾选选项 意思就是&#xff1a; Use WSL 2 instead of Hyper-V (recommended) : 启用虚拟化&#xff0c;…

20240727生活沉思------------关于报考软考高级架构师

软考高级架构师 软考高级架构师 缴费 主要是报的千峰 1880元。 相对来说还算可以吧。。。其他也没给我机会选择啊 备考 我现在开始备考&#xff0c;考试时间2024年11月。 今天是正式开始7.27号。 给大家看看接下来我的课程安排&#xff1a; 额&#xff0c;还是满满当当的…

Redis从入门到超神-(十二)Redis监听Key的过期事件

前言 试想一个业务场景&#xff0c;订单超过30分钟未支付需要做自动关单处理,修改订单状态&#xff0c;库存回退等&#xff0c;你怎么实现&#xff1f;方案一&#xff1a;可以使用定时任务扫表&#xff0c;通过支付状态和下单时间来判断是否支付过期。但是这样的方案是非常消耗…

Vue入门(二)常用指令

一、Vue 常用指令 Vue 常用指令 - 指令&#xff1a;是带有 v- 前缀的特殊属性&#xff0c;不同指令具有不同含义。例如 v-html&#xff0c;v-if&#xff0c;v-for。 - 使用指令时&#xff0c;通常编写在标签的属性上&#xff0c;值可以使用 JS 的表达式。 - 常用指令 二、常用…

邦布带你从零开始实现图书管理系统(java版)

今天我们来从零开始实现图书管理系统。 图书管理系统 来看我们的具体的实现&#xff0c;上述视频。 我们首先来实现框架&#xff0c;我们要实现图书管理系统&#xff0c;首先要搭框架。 我们首先定义一个书包&#xff0c;在书包中定义一个书类和一个书架类&#xff0c;再定义…

AI大模型写的高考作文,你觉得怎么样?

下方为2024年高考新课标I卷语文作文题目&#xff0c;接下来将使用Chatgpt、文心一言、讯飞星火等众多AI大模型来写这篇高考作文 Chatgpt 标题&#xff1a;问题的演变与思考 随着互联网和人工智能技术的飞速发展&#xff0c;我们获得信息的方式和速度发生了前所未有的变化。曾经…

用PyTorch从零开始编写DeepSeek-V2

DeepSeek-V2是一个强大的开源混合专家&#xff08;MoE&#xff09;语言模型&#xff0c;通过创新的Transformer架构实现了经济高效的训练和推理。该模型总共拥有2360亿参数&#xff0c;其中每个令牌激活21亿参数&#xff0c;支持最大128K令牌的上下文长度。 在开源模型中&…

C嘎嘎浅谈模板

这篇文章给大家介绍一下c嘎嘎内存管理和模板&#xff0c;那么我们直接进入正题 c/c的程序内存分布 这里的了解一下即可 new和delete的定义和操作 格式&#xff1a;类型* 对象名 new 类型&#xff1b; 数组(对象)定义格式&#xff1a;类型* 对象名 new 类型[元素个数]&…

【安卓开发】【Android】如何进行真机调试【注意事项】

一、所需原料 1、电脑&#xff08;安装有Android Studio开发工具&#xff09;&#xff1a; 2、安卓操作系统手机&#xff1a;笔者演示所用机型为huawei rongyao50&#xff0c;型号为NTU-AN00&#xff1a; 3、数据线&#xff08;usb-typeA&#xff09;一根。 二、操作步骤 1…

支持向量机回归及其应用(附Python 案例代码)

使用支持向量机回归估计房价 让我们看看如何使用支持向量机&#xff08;SVM&#xff09;的概念构建一个回归器来估计房价。我们将使用sklearn中提供的数据集&#xff0c;其中每个数据点由13个属性定义。我们的目标是根据这些属性估计房价。 引言 支持向量回归&#xff08;SV…

IndexError: index 0 is out of bounds for axis 1 with size 0

IndexError: index 0 is out of bounds for axis 1 with size 0 目录 IndexError: index 0 is out of bounds for axis 1 with size 0 【常见模块错误】 【解决方案】 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#…

Linux网络工具“瑞士军刀“集合

一、背景 平常我们在进行Linux服务器相关运维的时候&#xff0c;总会遇到一些网络相关的问题。我们可以借助这些小巧、功能强悍的工具帮助我们排查问题、解决问题。 下面结合之前的一些使用经验为大家介绍一下一些经典应用场景下&#xff0c;这个网络命令工具如何使用的。例如怎…

关于Redis(热点数据缓存,分布式锁,缓存安全(穿透,击穿,雪崩));

热点数据缓存: 为了把一些经常访问的数据&#xff0c;放入缓存中以减少对数据库的访问频率。从而减少数据库的压力&#xff0c;提高程序的性能。【内存中存储】成为缓存; 缓存适合存放的数据: 查询频率高且修改频率低 数据安全性低 作为缓存的组件: redis组件 memory组件 e…

大模型算法备案流程最详细说明【流程+附件】

文章目录 一、语料安全评估 二、黑盒测试 三、模型安全措施评估 四、性能评估 五、性能评估 六、安全性评估 七、可解释性评估 八、法律和合规性评估 九、应急管理措施 十、材料准备 十一、【线下流程】大模型备案线下详细步骤说明 十二、【线上流程】算法备案填报…

手把手教小白微信小程序开发(超详细保姆式教程)

注册&#xff1a;微信公众平台 -> 立即注册 ->小程序 AppID(小程序ID) wx05c13b331acc9d01 AppSecret(小程序密钥) 4f8232c7bbd4801e58a166d72e92e529 安装 微信开发者工具 &#xff0c;扫描就可以登录 设置&#xff1a;右上角设置 ->外观浅色&#xff0c;代理&am…

C++通过进程句柄、进程id或进程名去杀掉进程(附完整源码)

目录 1、通过进程句柄去杀进程 2、通过进程id去杀进程 3、通过进程名去杀进程 C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931Windows C++ 软件开发从入门到精通(专栏文章,持续更…

普中51单片机:蜂鸣器的简单使用(十一)

文章目录 引言蜂鸣器的分类工作原理无源蜂鸣器压电式蜂鸣器&#xff1a;电磁式蜂鸣器&#xff1a; 电路符号及应用代码演示——无源蜂鸣器 引言 蜂鸣器是一种常见的电子音响器件&#xff0c;广泛应用于各种电子产品中。它们能够发出不同频率的声音&#xff0c;用于警报、提醒、…

AI软件测试|人工智能测试中对抗样本生成攻略

从医疗诊断、自动驾驶到智能家居&#xff0c;人工智能技术为各个行业领域带来无限可能的同时&#xff0c;挑战也日益显现。特别是在人工智能安全领域&#xff0c;随着恶意攻击和数据欺骗的不断演变&#xff0c;确保AI系统的安全性和可靠性成为亟需解决的重要问题&#xff0c;对…