IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 第101篇 C++数据结构(十一)红黑树的插入 -> 正文阅读

[数据结构与算法]第101篇 C++数据结构(十一)红黑树的插入

红黑树更详细的介绍一搜一大把,不作过多的说明。

红黑树特性

1.结点是黑色或红色
2.根节点是黑色
3.叶子结点是黑色的空结点
4.任意节点到其每个叶子结点的所有路径都包含相同数目的黑色结点
5.红色结点的父结点和子结点都是黑色结点

红黑树特性推论

1.如果一个结点只有一个孩子,那么该结点的颜色一定是黑色的,且该结点的孩子一定是红色的,如果其是红色或者其孩子是黑色,违反了第4条特性
2.如果一个结点没有孩子,那么该结点可能是黑色,也可能是红色
3.如果一个黑色结点有孩子,在只有一个孩子的情况下,该孩子一定是红色,如果有两个孩子,那么孩子可能是都是黑色,也可能是都是红色,也有可能是一红一黑
4.如果一个黑色结点没有孩子,如果这个结点不是根节点,那么这个结点一定有兄弟,如果该结点的父结点是红色,那么兄弟可能是黑色,也可能是红色,如果该结点的父结点是黑色,那么兄弟结点一定是黑色

红黑树的插入

为了方便插入之后调整,插入时如下:
1.如果结点是空,即是根节点,则直接分配内存,然后进入调整
2.如果插入值大于该结点的值
1).如果该结点有右孩子,则往右边插入
2).否则为当前结点的右孩子分配内存,然后调整
3.如果插入值小于该结点的值
1).如果该结点有左孩子,则往左边插入
2).否则为当前结点的左孩子分配内存,然后调整

红黑树的插入代码

void insert(RBTNodePtr& node, _DataType value)
{
	/*如果结点是空,即是根节点,则直接分配内存,然后进入调整*/
	if (!node)
	{
		node = new RBTNode<_DataType>(value);
		insertFix(node, node->m_parent);
	}
	else
	{
		/*如果插入值大于该结点的值*/
		if (value > node->m_value)
		{
			/*如果该结点有右孩子,则往右边插入*/
			if (node->m_rightChild)
			{
				insert(node->m_rightChild, value);
			}
			/*否则为当前结点的右孩子分配内存,然后调整*/
			else
			{
				node->m_rightChild = new RBTNode<_DataType>(value, node);
				insertFix(node->m_rightChild, node);
			}
		}
		/*如果插入值小于该结点的值*/
		else
		{
			/*如果该结点有左孩子,则往左边插入*/
			if (node->m_leftChild)
			{
				insert(node->m_leftChild, value);
			}
			/*否则为当前结点的左孩子分配内存,然后调整*/
			else
			{
				node->m_leftChild = new RBTNode<_DataType>(value, node);
				insertFix(node->m_leftChild, node);
			}
		}
	}
}

红黑树的插入的情况

1.插入的结点是根结点,此时只需把结点染成黑色即可
2.插入的结点的父结点是黑色,则不需做任何调整,因为红色结点不影响黑高
3.插入的结点的父结点是红色,此时有两个连起来的红色结点,违反了红黑树的特性,因此需要对红黑树做调整

红黑树的插入调整

1.如果新插入的结点有叔叔结点,且叔叔结点的颜色是红色(父结点是红色的),则将父结点和叔叔结点都染成黑色,将祖父结点染成红色,把祖父结点当作新插入结点向上调整
2.如果新插入的结点没有叔叔结点或者叔叔结点时黑色,则:
1).如果父结点是祖父结点的左孩子且新插入的结点是父结点的左孩子,则将父结点染成黑色,将祖父结点染成红色,对祖父结点进行右旋(LL)
2).如果父结点是祖父结点的右孩子且新插入的结点是父结点的右孩子,则将父结点染成黑色,将祖父结点染成红色,对祖父结点进行左旋(RR)
3).如果父结点是祖父结点的左孩子且新插入的结点时父结点的右孩子,则将新插入的结点染成黑色,将祖父结点染成红色,对父结点进行左旋,然后对祖父结点进行右旋(LR)
4).如果父结点是祖父结点的右孩子且新插入的结点时父结点的左孩子,则将新插入的结点染成黑色,将祖父结点染成红色,对父结点进行右旋,然后对祖父结点进行左旋(RL)

红黑树的插入调整代码

就按照上面的过程写就可以了。

void insertFix(RBTNodePtr node, RBTNodePtr nodeParent)
{
	/*插入的结点是根结点,此时只需把结点染成黑色即可*/
	if (!nodeParent)
	{
		node->m_color = Color::BLACK;
		return;
	}
	/*插入的结点的父结点是黑色,则不需做任何调整,因为红色结点不影响黑高*/
	else if (nodeParent->m_color == Color::BLACK)
	{
		return;
	}
	/*插入的结点的父结点是红色,此时有两个连起来的红色结点,违反了红黑树的特性,因此需要对红黑树做调整*/
	else
	{
		RBTNodePtr nodeGrandFather = nodeParent->m_parent;
		RBTNodePtr nodeUncle = (nodeParent == nodeGrandFather->m_leftChild) ? 
			nodeGrandFather->m_rightChild : 
			nodeGrandFather->m_leftChild;
		/*如果新插入的结点有叔叔结点,且叔叔结点的颜色是红色(父结点是红色的),则将父结点和叔叔结点都染成黑色,
		将祖父结点染成红色,把祖父结点当作新插入结点向上调整*/
		if (nodeUncle && nodeUncle->m_color == Color::RED)
		{
			nodeUncle->m_color = Color::BLACK;
			nodeParent->m_color = Color::BLACK;
			nodeGrandFather->m_color = Color::RED;
			insertFix(nodeGrandFather, nodeGrandFather->m_parent);
		}
		/*如果新插入的结点没有叔叔结点或者叔叔结点时黑色*/
		else
		{
			/*如果父结点是祖父结点的左孩子且新插入的结点是父结点的左孩子,则将父结点染成黑色,
			将祖父结点染成红色,对祖父结点进行右旋(LL)*/
			if (nodeParent == nodeGrandFather->m_leftChild && node == nodeParent->m_leftChild)
			{
				nodeParent->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				rightRotate(nodeGrandFather);
			}
			/*如果父结点是祖父结点的右孩子且新插入的结点是父结点的右孩子,则将父结点染成黑色,
			将祖父结点染成红色,对祖父结点进行左旋(RR)*/
			else if (nodeParent == nodeGrandFather->m_rightChild && node == nodeParent->m_rightChild)
			{
				nodeParent->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				leftRotate(nodeGrandFather);
			}
			/*如果父结点是祖父结点的左孩子且新插入的结点时父结点的右孩子,则将新插入的结点染成黑色,
			将祖父结点染成红色,对父结点进行左旋,然后对祖父结点进行右旋(LR)*/
			else if (nodeParent == nodeGrandFather->m_leftChild && node == nodeParent->m_rightChild)
			{
				node->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				leftRotate(nodeParent);
				rightRotate(nodeGrandFather);
			}
			/*如果父结点是祖父结点的右孩子且新插入的结点时父结点的左孩子,则将新插入的结点染成黑色,
			将祖父结点染成红色,对父结点进行右旋,然后对祖父结点进行左旋(RL)*/
			else
			{
				node->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				rightRotate(nodeParent);
				leftRotate(nodeGrandFather);
			}
		}
	}
}

红黑树的插入总结

先了解红黑树的特性,然后再分析插入时面临的情况,再去做打算怎么调整,这里没图,但是如果已经对红黑有一定的了解,应该可以看懂吧,我也是看了很多篇,看了很多视频才自己真正的了解。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:54:13  更:2022-05-18 17:54:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 7:16:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码