栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

第101篇 C++数据结构(十一)红黑树的插入

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第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
		{
			
			if (nodeParent == nodeGrandFather->m_leftChild && node == nodeParent->m_leftChild)
			{
				nodeParent->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				rightRotate(nodeGrandFather);
			}
			
			else if (nodeParent == nodeGrandFather->m_rightChild && node == nodeParent->m_rightChild)
			{
				nodeParent->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				leftRotate(nodeGrandFather);
			}
			
			else if (nodeParent == nodeGrandFather->m_leftChild && node == nodeParent->m_rightChild)
			{
				node->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				leftRotate(nodeParent);
				rightRotate(nodeGrandFather);
			}
			
			else
			{
				node->m_color = Color::BLACK;
				nodeGrandFather->m_color = Color::RED;
				rightRotate(nodeParent);
				leftRotate(nodeGrandFather);
			}
		}
	}
}
红黑树的插入总结

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/887362.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号