红黑树的topdown-remove

红黑树的bottomup-insert很容易实现, 而删除就不容易, 今天抄成功了Julienne Walker发在他网站上的算法, 为备忘, 总结一下。

首先, 删除red 节点, 不影响红黑树的有效性。利用这一点,我们寄希望于可以把其他情况都转化成删除红色节点。

其次, 跟在Binary search tree中一样, 删除一个节点K可以转化为

        1,先找到这个节点的inorder predecessor(中序前一个) $K

        2, 拷贝$K的内容到K,然后删除$K

Julienne Walker告诉我们,要转化成删除红色节点总是可以的。只要我们在向下搜索待删除key的时候,利用旋转,确保被删除的节点是红色, 并且不改变红黑树的性质(1,红色节点不能相连;2,每一个空节点到root的“black-height”都一样)

 

结合上面两点, 我们在搜索的过程中要把实际上“物理”删除的节点变成红色的, 具体变换如下:

假定刚刚比较过Q.data与data的大小, 知道该往Q的子节点T的方向继续搜索.(在找到Q.data == data后, 还继续搜索$Q,

为了让T的某个分支上满足设想, 即最后让$Q为红色, 我们希望将Q变成红色的, 如果它不是红的的话)

RBTreeRemove

void RedBlackTree::remove(int data)
{
	if (mRoot != NULL)
	{
		RBNode head = {0};
		//great-parent, parent, iterator,     ,founded node.
		RBNode *g,        *p,      *q,    *t,     *f = NULL;
		
		q = &head;
		g = p = NULL;
		q->r = mRoot;
		bool isRight = true;

		do
		{
			bool last = isRight;
			t = isRight ? q->r : q->l;
			g=p; p=q; q = t;
			isRight = q->data < data;
			t = isRight ? q->r : q->l;			
			
			if (q->data==data) f=q;

			if (!is_red(q) && !is_red(t))
			{//目标是使最后被删除的节点red, q或t是red都可以保证这一点
				RBNode* othLink = isRight ? q->l : q->r;
				if (is_red(othLink))
				{
					if (isRight) rotate_right(q);
					else rotate_left(q);
					if (last) p->l = q;
					else p->r = q;
				}
				else
				{
					RBNode* s = last ? p->l : p->r;
					if (s != NULL)
					{
						if (!is_red(s->l) && !is_red(s->r))
						{
							p->red = 0;
							q->red = s->red = 1;
						}
						else
						{
							bool isPLeft = g->l == p;
							RBNode *&tmp = isPLeft ? g->l : g->r;
							RBNode *ss = last ? s->l : s->r;
							if (is_red(ss))
							{
								if (last) rotate_right(tmp);
								else rotate_left(tmp);
							}
							else 
							{
								if (last) rotate_left_right(tmp);
								else rotate_right_left(tmp);
							}
							tmp->red = q->red = 1;
							tmp->l->red = tmp->r->red=0;
						}
					}
				}
			}
		}while (t != NULL);

		if (f != NULL)
		{
			f->data = q->data;
			RBNode* &tmp = p->l==q ? p->l : p->r;
			tmp=q->l == NULL ? q->r : q->l;
			delete q;
		}
		if (mRoot != NULL) mRoot->red = 0;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值