红黑树的自我实现

概念:

红黑树是一棵二叉搜索树,每个节点是红色或黑色。通过对每条从根节点到叶子结点路径上的节点的颜色限制,确保没有一条路径长度会超过其他路径长度的两倍,因而是接近平衡的。

所以AVL树比红黑树更集中。

红黑树的特点:

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

 

 

小问题:红黑树概念中说确保 没有一条路径会比其他路径长一倍,也就是说最长的路径长度绝不可能超过最短路径的2倍,why?

    首先根节点是黑的,黑节点的子结点可以是黑的也可以是红的,而红节点的子节点必须是黑的。并且根节点到叶节点的每条路径上的黑节点数量要求相等;所以最短路径上如果全为黑节点,有n个,那么最长路径上面一定有n个黑节点,另加上n个红节点。在增加节点就不符合红黑树的性质了。

红黑树代码实现: 

如果想看红黑树插入时更新的五种情况,可以直接通过目录移到“五种情况”的位置。

如果不明白红黑树的旋转,请看博客:https://mp.csdn.net/console/editor/html/106836542

插入:

当我们新插入节点之后,我们面临一个选择,新插入的节点是红色还是黑色呢?

如果插入的节点是红色的,而其父节点也是红色的,那么就违反了红节点的子结点是黑色的性质

如果插入的节点是黑色的,那么肯定违反了每个路径上的黑节点数量相同的性质。

相比之下,我们还是选择插入的节点是红节点,因为比较好调节。

那么插入一个红节点必定会面临两种选择

父节点是黑色的,符合红黑树性质;

父节点是红色的,不符合红黑树性质,我们需要进行调节;

图片解析:

我们  设 插入的节点为cur  其父节点为p  祖父节点为 g   父节点的兄弟节点为u

当我们插入节点后是否调节需要p节点判断,然而怎么调节我们有需要u节点判断

情况1:u节点不存在(因为u节点不存在,则一定是新插入节点造成的这种情况)

情况2:u存在且为红色

不论出于什么样的位置,这种情况我们只需要进行变色处理;

如果g节点的父节点不存在,即g节点肯定为父节点,再将g节点变为黑节点即可完成更新

如果g节点的父节点是黑色的,我们也完成了更新

如果g节点的父节点是红色的,我们还需要向上进行更新

情况3:u节点存在且为黑色

 

我们可以对上面的情况进行总结:

五种情况:

情况一: u存在且为红色:

不论什么情况,我们同样处理

g节点变为红色,p、u节点变为黑色

如果g节点的父节点不存在,即g节点肯定为父节点,再将g节点变为黑节点即可完成更新

如果g节点的父节点是黑色的,我们也完成了更新

如果g节点的父节点是红色的,我们还需要向上进行更新

情况二:u不存在或者为黑色      并且    p为g的左节点,cur为p的左节点

以g节点进行右旋,p节点变黑,g节点变红,更新完毕

情况三:u不存在或者为黑色      并且    p为g的右节点,cur为p的右节点

以g节点进行左旋,p节点变黑,g节点变红,更新完毕

情况四:u不存在或者为黑色      并且    p为g的左节点,cur为p的右节点

以p节点进行左旋,变为情况二

情况五:u不存在或者为黑色      并且    p为g的右节点,cur为p的左节点

以p节点进行右旋,变为情况三

代码实现:

	bool insert(const pair<K, V>& data)
	{

		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_color = Black;
			return true;
		}
		else
		{
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur != nullptr)
			{
				if (cur->_data.first < data.first)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (cur->_data.first>data.first)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}
			//插入新节点,将新节点默认给成红色
			cur = new Node(data);
			if (parent->_data.first< data.first)
			{
				parent->_right = cur;
			}
			else if (parent->_data.first>data.first)
			{
				parent->_left = cur;
			}
			cur->_color = Red;
			cur->_parent = parent;


			//判断当前树是否符合红黑树性质,不符合则进行调整
			while (parent != nullptr&&parent->_color == Red)
			{
				Node* grandfather = parent->_parent;
				if (parent == grandfather->_left)
				{
					Node* uncle = grandfather->_right;
					//叔叔存在且为红色,那么我们只需要变色
					//父节点和叔叔节点变为黑色
					//祖父节点变为红色
					if (uncle != nullptr&&uncle->_color == Red)
					{
						parent->_color = uncle->_color = Black;
						grandfather->_color = Red;
						//向上更新
						cur = grandfather;
						parent = cur->_parent;
					}
					else
					{
						//叔叔不存在或者为黑色

						
							//如果cur是父节点的左节点,右单旋+父节点变黑、祖父节点变红
							//如果cur是父节点的右节点,需要进行双旋操作


							if (cur == parent->_right)
							{
								RotateL(parent);
								swap(parent, cur);
							}
							
								RotateR(grandfather);
								parent->_color = Black;
								grandfather->_color = Red;
								break;
					}
				}

				else   //if (parent == grandfather->_right)
				{
					Node* uncle = grandfather->_left;
					//叔叔存在且为红色,那么我们只需要变色
					//父节点和叔叔节点变为黑色
					//祖父节点变为红色
					if (uncle != nullptr&&uncle->_color == Red)
					{
						parent->_color = uncle->_color = Black;
						grandfather->_color = Red;
						//向上更新
						cur = grandfather;
						parent = cur->_parent;
					}
					else
					{
						//叔叔不存在或者为黑色

						
							if (cur == parent->_left)
							{
								RotateR(parent);
								swap(cur, parent);

							}
							RotateL(grandfather);
							parent->_color = Black;
							grandfather->_color = Red;
							break;

						
					}
				}

			}
			_root->_color = Black;
			return true;
		
		}

		
	}

 

谢谢你们的观看!

创作不易,不要白嫖哦! 小伙伴,动动手点个赞,(*^▽^*)!

注:如果本篇博客有任何错误和建议,欢迎伙伴们留言,你快说句话啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值