浅显易懂红黑树旋转/手动实现旋转代码

红黑树性质

1.不能有连在一起的红色节点
2. 每个红色节点的子节点都是黑色
3. 叶子结点都是黑色
4. 根节点都是黑色
5. 对每个结点,从该结点到其后代叶结点的简单路径上,均包含相同数目的黑色结点。
为了满足这些性质,最后就形成AVL,但是其实并不严格,就是说它的左右子树深度差可以大于1,但是正是因为这样,而让旋转更加容易,因此它的缓冲平衡机制就更容易实现。
红黑树中最长支路的长度必然“不大于”最短者的2倍,所以不妨设Max者为H,Min者为h。则有:H<=2h。

但是其实考虑到在操作过程中还有一部上色操作,其实跟普通的AVL操作复杂度差不多,但是又考虑到红黑树更容易实现,因此在C++中map和set底层还是用的红黑树

红黑树的旋转

红黑树一共又三种平衡机制: 变色,左旋,右旋;
这里我们用一种很经典的例子来概括三种变换方式;
我们有一颗这样的红黑树
在这里插入图片描述
然后我们想插入一个节点6,由于查找二叉树的性质,我们必须这样插入
值得注意的是,插入的点都必须默认为红色
在这里插入图片描述
我们发现下方6,和7连续为红色,因此我们首先变色变成这样
将连续的红色中的一个和其父结点的黑色颜色互换(如果是父结点就与其另外一个子节点换颜色)
在这里插入图片描述
然后我们发现还是又12和5连续为红色,这个时候如果再变色是不行的了,因为再变的话根节点就不是黑色了。
由于连续的在左边,因此我们需要用到左旋,变成这样

我们先不看19以及右边那一坨,先以只以左子树为准,我么不难发现就是以7及其下面对依托为旋转中心,这一坨不动,其余的向左向左旋转了一圈,旋转之后,12就变成了根,然后我们再讲7这一坨挂到左边就行。

这就是所谓的左旋
在这里插入图片描述
左旋之后,我们发现,其实还是没有满足红黑树性质要求,又因为连续的在右边,这个时候我们需要右旋,变成这样
其实也就是以13为旋转中心向右旋转一圈,这个时候,12就变成了根节点,然后我们再把13挂到右边一坨就行
在这里插入图片描述
然后我们发现其实还是没有满足要求,这个时候我们还需要再来一次颜色的改变变成这样
这个时候就平衡了
在这里插入图片描述
以左旋为例

enum Color
{
	R,
	B,
};
struct BRNode
{
	int data;
	int color = R;
	BRNode *left;
	BRNode *right;
	BRNode *father;
	BRNode(int data) : data(data){};
};
class BRtree
{
private:
	static BRNode *root;
public:
	void myinsert(int innum, BRNode* node = root)//应该不允许重复
	{
		if (root->data < innum)
		{
			if (root->right == NULL)
			{
				root->right = new BRNode(innum);
			}
			else
			{
				myinsert(innum, root->right);
			}
		}
		else
		{
			if (root->left == NULL)
			{
				root->left = new BRNode(innum);
			}
			else
			{
				myinsert(innum, root->left);
			}
		}
	}
	void leftRotate(BRNode* node)
	{
		if (node->father == NULL)
		{
			BRNode *E = root;
			BRNode* S = E->right;
			//将下面一坨移到左边
			E-> right = S->left;
			S->left->father = E;
			//旋转节点
			S->left = E;
			E->father = S;
			S->father = NULL;
		}
		else
		{
			if (node == node->father->left)//如果要旋转的中心是父结点的左子树根
			{
				node->father->left = node->right;//重新定义子树根节点
			}
			else
			{
				node->father->right = node->right;
			}
			//更改新的次根节点的父结点
			node->right->father = node->father;
			//更改本结点的父结点
			node->father = node->right;
			node->right->left = node;
			//重新挂载旋转中心
			node->right = node->right->left;
			node->right->father = node;
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无情の学习机器

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值