c++红黑树,插入公式

概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或

Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路

径会比其他路径长出俩倍,因而是接近平衡的。

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

插入

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

检测新节点插入后,红黑树的性质是否造到破坏

因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何

性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连

在一起的红色节点,此时需要对红黑树分情况来讨论:

约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

情况一

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

情况二

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

情况三

其实就是需要双旋的情况

代码:

cpp 复制代码
	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;

	}

红黑树的验证

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

cpp 复制代码
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);
}
相关推荐
the_nov12 分钟前
20.IP协议
linux·服务器·网络·c++·tcp/ip
只有月亮知道23 分钟前
C++list常用接口和模拟实现
开发语言·c++
勘察加熊人35 分钟前
c#和c++脚本解释器科学运算
开发语言·c++·c#
明月看潮生1 小时前
青少年编程与数学 02-016 Python数据结构与算法 03课题、数组与链表
数据结构·python·青少年编程·编程与数学
zyx没烦恼2 小时前
Linux 下 日志系统搭建全攻略
linux·服务器·开发语言·c++
苏卫苏卫苏卫2 小时前
【Python】数据结构练习
开发语言·数据结构·笔记·python·numpy·pandas
weisian1512 小时前
力扣经典算法篇-9-跳跃游戏(贪心算法,反向递推)
算法·leetcode·游戏
MCYH02063 小时前
C++抽卡模拟器
java·c++·算法·概率·原神
pystraf3 小时前
P10587 「ALFR Round 2」C 小 Y 的数 Solution
数据结构·c++·算法·线段树·洛谷
ゞ 正在缓冲99%…3 小时前
leetcode221.最大正方形
java·算法·动态规划