270-RBTree(红黑树)

RBTree(红黑树)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
红色节点不容许连续,黑色节点容许连续。根一定是黑色的,哨兵节点一定是黑色的。从任意节点出发到达哨兵节点的黑色节点个数要一致。
红黑树近似于平衡。

红黑树的定义

typedef enum { RED = 0, BLACK = 1 } ColorType; 
typedef int KeyType;
typedef struct rb_node
{
	rb_node *leftchild;//左孩子 
	rb_node *parent;//双亲 
	rb_node *rightchild;//右孩子 
	ColorType color;//颜色结点,红,黑 
	KeyType  key;//关键码 
}rb_node;


typedef struct
{
	struct rb_node* root;//根节点 
	struct rb_node* NIL; //空节点 
	int cursize;//个数 
}RBTree;

理解红黑树

在这里插入图片描述
我们看左图,如果从最上面的黑色节点出发,路径上看黑色数目都是2个,看右图,从最顶点的红色出发,黑色数目都是2个,这两个图是一样的。不会发生变化。

在这里插入图片描述
当我们插入第一个数据12,颜色必须是红色,但是它作为根节点,它的颜色由红色变为黑色,还有一个黑色节点作为哨兵节点,12的左孩子和右孩子都指向哨兵节点,插入23,颜色都是红色,双亲是黑色,可以(不许红色连续),我们插入34,34也是红色,在右边插入,但是它的双亲是红色,不行,就找双亲的双亲的左边,但是是哨兵节点(黑色),无法通过着色的改变来确定黑色的数目。
在这里插入图片描述
我们就以23位基准,把12绕到23,进行左旋转。23替代12的位置,23变为黑,12变为红。
在这里插入图片描述
我们插入45,45是红色,45的双亲是红色,找双亲的双亲的左边也是红色
在这里插入图片描述
我们插入56,56是红色,双亲是红色,双亲的双亲的左边是哨兵,不能调整,只能进行旋转,把34改为红色,左单旋转。
在这里插入图片描述
我们插入50,双亲是红色,在56的左边,在折线上,双亲的双亲的左边是红色
在这里插入图片描述
我们插入78,大于56,颜色是红色,双亲是黑色,不需要调整。
在这里插入图片描述
我们插入89,是红色,双亲是红色,双亲的双亲的左边是红色
在这里插入图片描述
在这里插入图片描述

购买节点

rb_node* Buynode(KeyType kx)//购买结点 
{
	rb_node* s = (rb_node*)malloc(sizeof(rb_node));
	if (nullptr == s) exit(1);
	memset(s, 0, sizeof(rb_node));
	s->color = RED;
	s->key = kx;
	return s;
}

void Freenode(rb_node* p)//释放结点 
{
	free(p);
}

左旋转

void RotateLeft(RBTree& tree, rb_node* ptr)//左旋转 
{
	rb_node* newroot = ptr->rightchild;
	newroot->parent = ptr->parent;// 1
	ptr->rightchild = newroot->leftchild;
	if (newroot->leftchild != nullptr)
	{
		newroot->leftchild->parent = ptr;// 2
	}
	newroot->leftchild = ptr;
	if (ptr->parent == nullptr)
	{
		tree.root = newroot;
	}
	else
	{
		if (ptr->parent->leftchild == ptr)
		{
			ptr->parent->leftchild = newroot;
		}
		else
		{
			ptr->parent->rightchild = newroot;
		}
	}
	ptr->parent = newroot;	 // 3
}

右旋转

void RotateRight(RBTree& tree, rb_node* ptr)//右旋转 
{
	rb_node* newroot = ptr->leftchild;
	newroot->parent = ptr->parent;//1
	ptr->leftchild = newroot->rightchild;
	if (newroot->rightchild != nullptr)
	{
		newroot->rightchild->parent = ptr;
	}
	newroot->rightchild = ptr;
	if (ptr->parent == nullptr)
	{
		tree.root = newroot;
	}
	else
	{
		if (ptr->parent->leftchild == ptr)
		{
			ptr->parent->leftchild = newroot;
		}
		else
		{
			ptr->parent->rightchild = newroot;
		}
	}
	ptr->parent = newroot;
}

插入和调整

void Adjust_RBTree(RBTree& tree, rb_node *ptr) 
{
	rb_node* _X = nullptr;
	while (ptr->parent != nullptr && ptr->parent->color != BLACK)
	{
		if (ptr->parent->parent->rightchild == ptr->parent)
		{
			_X = ptr->parent->parent->leftchild;
			if (_X->color == RED)
			{
				ptr->parent->color = BLACK;
				_X->color = BLACK;
				ptr->parent->parent->color = RED;
				ptr = ptr->parent->parent;
			}
			else
			{
				if (ptr->parent->leftchild == ptr)
				{
					ptr = ptr->parent;
					RotateRight(tree, ptr);
				}
				ptr->parent->color = BLACK;
				ptr->parent->parent->color = RED;
				RotateLeft(tree, ptr->parent->parent);
			}

		}
		else  // left 
		{
			_X = ptr->parent->parent->rightchild;
			if (_X->color == RED)
			{
				ptr->parent->color = BLACK;
				_X->color = BLACK;
				ptr->parent->parent->color = RED;
				ptr = ptr->parent->parent;
			}
			else
			{
				if (ptr->parent->rightchild == ptr)
				{
					ptr = ptr->parent;
					RotateLeft(tree, ptr);
				}
				ptr->parent->color = BLACK;
				ptr->parent->parent->color = RED;
				RotateRight(tree, ptr->parent->parent);
			}
		}
	}
	tree.root->color = BLACK;
}



bool Insert(RBTree& tree, KeyType kx)
{
	rb_node* p = Buynode(kx);
	Adjust_RBTree(tree, p);
	return true;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

林林林ZEYU

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

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

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

打赏作者

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

抵扣说明:

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

余额充值