C++红黑树:插入与平衡操作详解

06-02 1195阅读

                                欢迎来到干货小仓库

                                        奔跑吧,少年

C++红黑树:插入与平衡操作详解


1.红黑树的概念

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

C++红黑树:插入与平衡操作详解

2.红黑树性质 

1. 每个结点不是红色就是黑色

2. 根节点是黑色的 

3. 如果一个节点是红色的,则它的两个孩子结点是黑色的 

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

5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

C++红黑树:插入与平衡操作详解

3.AVL树 和 红黑树的区别

 

C++红黑树:插入与平衡操作详解

 4.红黑树的插入

情况一:当插入的节点其父节点的颜色是黑色那就没问题

C++红黑树:插入与平衡操作详解

情况二: 当新插入节点其父节点是红色那就需要调整

①其uncle存在,且为红色(变色+继续向上更新)

C++红黑树:插入与平衡操作详解

 ②其uncle不存在(旋转+变色)

C++红黑树:插入与平衡操作详解

③其uncle存在且为黑(旋转+变色) 

C++红黑树:插入与平衡操作详解

综合上面需要更新的情况总结:

红黑树插入这么更新关键看uncle

1、uncle存在且为红------ 策略:变色+继续往上更新

2、uncle不存在 ------策略:旋转+继续往上更新

3、uncle存在且为黑------策略:旋转+继续往上更新(这种情况由 第一种情况演变而来) 

 5.红黑树底层结构

enum COLOR
{
	RED,
	BLACK
};
template
struct RBTreeNode
{
	pair _kv;
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	COLOR _color;
	RBTreeNode(const pair& kv)
		:_kv(kv)
		,_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_color(COLOR::RED)
	{ }
};
template
class RBTree
{
	typedef RBTreeNode  Node;
 private:
	Node* _root=nullptr;
};
    

6.插入逻辑代码

bool insert(const pair& kv)
{
	//二叉搜索树的插入
	if (_root == nullptr)
	{
		Node* newNode = new Node(kv);
		_root = newNode;
		_root->_color = BLACK;
		return true;
	}
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		if (cur->_kv.first > kv.first)
		{
			parent = cur;
			cur = cur->_left;
		}
		else if (cur->_kv.first _right;
		}
		else
			return false;
	}
	cur = new Node(kv);
	if (parent->_kv.first > cur->_kv.first)
	{
		parent->_left = cur;
	}
	else
	{
		parent->_right = cur;
	}
	cur->_parent = parent;
	//调节颜色
	while (parent && parent->_color == RED)
	{
		Node* grandfather = parent->_parent;
		if (grandfather->_left == parent)
		{
			Node* uncle = grandfather->_right;
			if (uncle && uncle->_color == RED)
			{
				//变色
				parent->_color = uncle->_color = BLACK;
				grandfather->_color = RED;
				//继续向上处理
				cur = grandfather;
				parent = cur->_parent;
			}
			else //(uncle==nullptr || (uncle && uncle->_color==BLACK))
			{
				if (parent->_left == cur)
				{
					//		g
					//    p
					//	c
					RotateR(grandfather); //右旋
					parent->_color = BLACK;
					grandfather->_color = RED;
				}
				else if ( parent->_right == cur)
				{
					//     g
					//   p
					//		c
					RotateL(parent);  //左旋
					RotateR(grandfather); //右旋
					cur->_color = BLACK;
					grandfather->_color = RED;
				}
				else
					assert(false);
				break;
			}
		}
		else //grandfather->_right == parent
		{
			Node* uncle = grandfather->_left;
			if (uncle && uncle->_color == RED)
			{
				//变色
				parent->_color = uncle->_color = BLACK;
				grandfather->_color = RED;
				//继续向上处理
				cur = grandfather;
				parent = cur->_parent;
			}
			else  //uncle不存在/uncle存在且为黑
			{
				
				if ( parent->_right == cur)
				{
					// g
					//	  p
					//       c
					RotateL(grandfather); //左旋
					grandfather->_color = RED;
					parent->_color = BLACK;
				}
				else if (parent->_left == cur)
				{
					// g
					//	  p
					// c
					RotateR(parent); //右旋
					RotateL(grandfather); //左旋
					cur->_color = BLACK;
					grandfather->_color = RED;
				}
				else
					assert(false);
				break;
			}
		}
	}
	_root->_color = BLACK;
	return true;
}
//左旋
void RotateL(Node* parent)
{
	++rotateCount;
	Node* cur = parent->_right;
	Node* curLeft = cur->_left;
	if (curLeft)
		curLeft->_parent = parent;
	parent->_right = curLeft;
	Node* ppNode = parent->_parent;
	parent->_parent = cur;
	cur->_left = parent;
	//修改cur的父亲
	if (ppNode == nullptr)
	{
		cur->_parent = nullptr;
		_root = cur;
	}
	else
	{
		if (ppNode->_left == parent)
			ppNode->_left = cur;
		else
			ppNode->_right = cur;
		cur->_parent = ppNode;
	}
}
//右旋
void RotateR(Node* parent)
{
	++rotateCount;
	Node* cur = parent->_left;
	Node* curRight = cur->_right;
	parent->_left = curRight;
	if (curRight)
		curRight->_parent = parent;
	Node* ppNode = parent->_parent;
	parent->_parent = cur;
	cur->_right = parent;
	//修改cur的父亲
	if (ppNode == nullptr)
	{
		_root = cur;
		cur->_parent = nullptr;
	}
	else
	{
		if (ppNode->_left == parent)
			ppNode->_left = cur;
		else
			ppNode->_right = cur;
		cur->_parent = ppNode;
	}
}

觉得不错的,大家可以点赞+收藏咯

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码