红黑树 节点的删除

接上一篇。

红黑树的插入操作!

红黑树的删除继续分各种情况进行考虑。

首先考虑红黑树的单支情况,即只有父节点只有一个子节点,另外一个为NULL,这样的话,只有一种情况,即父节点为黑色,子节点为红色,因为其他情况都会是孩子为黑色,因为孩子为红色父为红色,则与红父黑子矛盾。而当孩子是黑色时,另一个孩子是黑色的NULL,则必定使左右路径上黑色节点数量不等。所以单支只能为黑父红子。

这里的单支情况,是对任意一点的,若其只有一个孩子,则其必为黑色,孩子必为红色,且孩子为叶子节点。孩子为红色,如果有孙子,其孙子必为黑色,则路径黑子数量不等,不平衡。

情况一:

单支,删除红色节点,则不会影响其他路径情况,不影响平衡,直接删除即可。

情况二:

单支,删除黑节点

若s节点为黑色,则用单支下的红色孩子替代自己,然后删除黑色节点,这样路径上少了一个黑色节点,影响平衡,需要进行调整。

情况三:

删除节点有两个非空孩子,这时候又用到向下旋转的思路,寻找删除节点p的中序遍历的后继节点s,即正常排序后位于p之后的数字,而且s节点必定最多有一颗子树,即s最多有一颗右子树,或者没有。若s节点有一颗右子树,则必为单支情况,其孩子为红色,且无孙子,则这就是情况二,转到情况二。若s节点为叶子节点,则其可为红色或黑色,红色为情况一。

这种情况将p与s的数据交换,但颜色不换,则情况转换为删除s点,而删除之前树还是平衡的。

或者这样分析:

若s节点为红色,则其必定不是单支,则其为叶子节点,则是情况一,直接删除即可。

若s节点为黑色,则用s的孩子null或者单支下的红色孩子替代自己,然后删除黑色节点,这样路径上少了一个黑色节点,影响平衡,需要进行调整。(这里又要注意,如果是孩子为NULL,替代后,如何找到s节点的父节点。没有哨兵节点,这个地方麻烦了。。。。好吧,调用的递归调整函数的参数加一个父节点指针)

然后如同插入一样设置一个递归的调整函数,调整有4种情况:

首先以删除判断节点为x,为黑色,父节点为p,兄弟节点为w。以x为根的子树的黑色节点树减一,则需要进行平衡操作。

一般是有一下4种情况,但,还有一个特殊情况,即x为根节点时,跟插入时判断相同,如果x为根节点,且现在为红色, 则将其改为黑色。对于以下情况2,可能转换到这种情况。第二次被别人的博客坑,等会写完了再测试有没有其他错误。

情况1:w为红色。

则w的孩子都为黑色,p为黑色。改变w和p的颜色,即w改为黑色,p改为红色,然后以p为支点进行左旋,或右旋,根据x位于p的位置决定,若x为左孩子,左旋,右孩子右旋。更新后x获得了新的兄弟节点,然后继续对x进行判断调节。

情况2:w为黑色,且w的孩子都为黑色。这里由于之前是在x所在子树上删除了一个黑色的节点,则w所在子树上必定有一个黑色节点,即w必定不为NULL。

将w置为红色,使w所在子树上黑色数量减一,则p所在子树上黑色节点数量也减一,则需要以p节点作为当前节点,即新的x节点。如果新的x为红,则将其置为黑色,则整个树平衡,结束,如果为黑,则继续判断新的x节点的情况。

情况3:w为黑色。

如果x为p的左孩子, w的左孩子为红色,右孩子为黑色。

则将w置为红色,左孩子为黑色,然后以w节点为支点右旋。

如果x为p的右孩子, w的右孩子为红色,左孩子为黑色、

则将w为红,右孩子为黑,然后以w节点左旋。

获得新的兄弟节点,进入情况4. 这里进行情况3的旋转不会对改变任何子树的平衡性。

情况4:w为黑色。

如果x为p的左孩子,w的右孩子为红色,左孩子可以为红色或黑色或NULL。

则交换w和p的颜色,因为之后w要成为新的父节点,所以要获得原来p的颜色,防止与p的父节点冲突。

将w的右孩子设置为黑色,这样w的右子树黑色节点树+1,

再以p节点为支点左旋,这样w的颜色黑色会移动到左子树,使其节点树 -1 + 1 =0,而右子树减少了一个黑节点 +1 -1 = 0;且新的p节点为原来的颜色,整个树是平衡的。结束、

如果x为p的右孩子,w的左孩子是红色。同理、

交换w和p的颜色,将w的做孩子改为黑色,以p为节点右旋。结束判断。

最终调整完成。这里也有一个很重要的地方,在左旋和右旋时交换父节点p与其对应左右孩子c的颜色,导致旋转后得到的新父节点p颜色未变,则不用再向上检测。

中间测试的时候有出错了,尝试画了一些图并找出了错误,只画了一张图,其他都是看别人的博客思考的。

删除其实也不是特别复杂,尝试写出代码:

template <typename T>
void RBTree<T>::GetParentLinked(RBNode<T> *a,RBNode<T> *b){
	if(a == root){
		root = b;
		if(b)
			b->parent = 0;
		return;
	}
	if(a->parent->left == a){
		a->parent->left = b;
		if(b)
			b->parent = a->parent;
	}else{
		a->parent->right = b;
		if(b)
			b->parent = a->parent;
	}

}
template <typename T>
bool RBTree<T>::Delete(const T &x){
	RBNode<T> *p = root ,*s,*fa;
	if(!root)return false;
	while(p){
		if(p->value == x)break;
		else if(x < p->value)p = p->left;
		else p = p->right;
	}
	if(p){
		if( p->left &&  p->right){//当存在左右孩子时,向下旋转
			s = p->right;
			while(s->left){
				s = s->left;
			}
			int temp = p->value;
			p->value = s->value;
			s->value = temp;
			p = s;
		}
		if(p->red){//为红色叶子节点,直接删除
			GetParentLinked(p,p->left);
			delete p;
		}else{//为黑色时,将其红色子孩子替代他
			//由于之前已经向下旋转,则这里只有一种特殊可能,即单支情况删除黑色根节点。
			fa = p->parent;//之后可能没有父节点。
			if(p->left){
				s = p->left;
				GetParentLinked(p,p->left);
			}
			else {
				s = p->right;
				GetParentLinked(p,p->right);
			}
			delete p;
			AdjustAfterDelete(s,fa);
		}
		return true;
	}else return false;

}
template <typename T>
void RBTree<T>::AdjustAfterDelete(RBNode<T> *x ,RBNode<T> *p){
	if(p){//如果有父指针,则有四种情况。
		RBNode<T> *w ;
		bool inLeftTree = true;//标记左右情况,左右情况不同旋转方向以及判断方式也不同。
		if(p->left == x)w = p->right;
		else {
			w = p->left;
			inLeftTree = false;
		}
		if(w->red){
			w->red = false;
			p->red = true;
			if(inLeftTree)
				LRotation(p);//以p为支点进行旋转,不用考虑当前节点是否为空。
			else
				RRotation(p);
			AdjustAfterDelete(x,p);
		}else{
			if( !GetColorWithNULL(w->left) && !GetColorWithNULL(w->right) ){
				w->red = true;
				x = p;
				if(x ->red)x->red = false;//出错一次,要根据新的x节点进行判断。
				else	AdjustAfterDelete(x,x->parent);
			}else if(( inLeftTree && GetColorWithNULL(w->right) ) //情况4
				|| ( !inLeftTree && GetColorWithNULL(w->left) )  ){
					bool tempRed = p->red;
					p->red = w->red;
					w->red = tempRed;
					if(inLeftTree){
						w->right->red = false;
						LRotation(p);
					}else{
						w->left->red = false;
						RRotation(p);
					}
			}else {//情况3
				w->red = true;
				if(inLeftTree){
					w->left->red = false;
					RRotation(w);
					AdjustAfterDelete(x,p);
				}else{
					w->right->red = false;
					LRotation(w);
					AdjustAfterDelete(x,p);
				}
			}
		}
	}else{//如果不存在父节点,则此节点为根节点,则置为黑色结束。
		if(x)
			x->red = false;
		return ;
	}

}

我的红黑树代码!

时间: 2024-10-09 21:36:34

红黑树 节点的删除的相关文章

一种新的删除红黑树节点的算法

转载请注明出处:http://blog.csdn.net/mxway/article/details/38080315 下面维基百科上红黑树的5个性质 1.      节点是红色或黑色 2.      根是黑色 3.      所有叶子都是黑色(叶子是NIL节点) 4.      每个红色节点必须有两个黑色的子节点.(从每个叶子到根的所有路径上不能有两个连续的红色节点.) 5.      从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点. 根据上面的5个性质,我们可以得出下面的结论:

红黑树插入和删除的情况分析

红黑树是特殊二叉查找树的一种,一颗红黑树有以下5种性质: 1.根节点为黑色. 2.每个节点不是黑色就是红色. 3.每个红色节点的两个儿子一定是黑色. 4.所有的叶子节点都是黑色.(注:这里的叶子节点并不是真正意义上的叶子节点,而是一种只有颜色属性但不存放数据的节点,而且其没有儿子节点) 5.一个红黑树的中任取一个节点,从它所在位置到其他任何叶子节点的简单路径上所经过的黑色节点数相同. 这2个性质决定了从根节点到叶子节点的最长路径不可能大于最短路径的2倍.所以红黑树是一个大致平衡的二叉树.但跟AV

红黑树、插入删除操作

二叉排序树 一棵自平衡的二叉排序树(二叉搜索树) 生成二叉排序树的过程是非常容易失衡的,最坏的情况就是一边倒(只有右/左子树),这样会导致二叉树的检索效率大大降低(O(n)). 为了维持二叉树的平衡,有各种的算法,如:AVL,SBT,伸展树,TREAP ,红黑树等等. 红黑树 红黑树需要满足5条性质: - 节点非红即黑 - 根节点是黑色 - 所有NULL结点称为叶子节点,且认为颜色为黑 - 所有红节点的子节点都为黑色,一条路径上不能出现相邻的两个红色结点 - 从任一节点到其叶子节点的所有路径上都

红黑树插入与删除完整代码(dart语言实现)

之前分析了红黑树的删除,这里附上红黑树的完整版代码,包括查找.插入.删除等.删除后修复实现了两种算法,均比之前的更为简洁.一种是我自己的实现,代码非常简洁,行数更少:一种是Linux.Java等源码版本的实现,实现的略为复杂,但效率更高.两种算法经过测试,在百万级的数据上效率不分伯仲:1000万的数据中,我自己的实现比Linux内核版本的运行时间多2秒左右. 红黑树的插入相对简单,本文中的代码实现与Linux源码版本也略有差异,效率差别不大. 其他方法,如查找.遍历等,比较简单,不多做解释.遍历

红黑树新解(删除)

4.1 元素删除 约定: 删除一个结点z,如果有该结点有子结点,需要查找该结点的左树最大值y来替换,同时又需要用叶结点x来替换y的位置. 在二叉树中删除一个结点有以下几种情况,以删除红结点为例,删除黑结点也差不多,最重要的多必须检查代替的结点是不是子结点,是不是黑结点. Tip: 算法导论中谈到找右树最小值,我这里以左树最大值来代替删除结点,只是left和right的替换而已,原理都是一样.可以参照 红黑树可视化网站,https://www.cs.usfca.edu/~galles/visual

数据结构——红黑树的删除节点操作

1. 红黑树的删除操作过程分析 1. 首先看一下普通搜索二叉树的删除操作,普通搜索二叉树删除结点找替代结点有3种情情景: 情景1:删除结点无子结点,直接删除 情景2:删除结点只有一个子结点 情景3:删除结点有两个子结点 在这里有一个重要的思路:删除结点被替代后,在不考虑结点的键值的情况下,对于树来说,可以认为删除的是替代结点. 基于此,上面所说的3种二叉树的删除情景可以相互转换并且最终都是转换为情景1. 对于情景2:删除结点用其唯一的子结点替换,子结点替换为删除结点后,直接删除 对于情景3:删除

数据结构之红黑树(三)——删除操作

删除一个节点相同有可能改变树的平衡性,并且,删除所造成的不平衡性比插入所造成的平衡性的修正更加复杂. 化繁为简是算法分析中一个经常使用的方法.以下我们将欲删除节点分为三大类:欲删除节点为叶子节点.欲删除节点仅仅有一个子节点和欲删除有两个子节点. 而欲删除节点有两种可能的颜色,也须要分别对待. 为简化讨论,我们以欲删除节点在左側的情况为例进行修正,假设欲删除节点在右側,进行镜像地修正操作就可以. 1. 欲删除节点是叶子节点 1.1 欲删除节点为红色,父节点必为黑色.必无兄弟节点. 仅仅有下图所看到

红黑树从头至尾插入和删除结点的全程演示图

红黑树插入和删除结点的全程演示 作者:July.saturnman.时间:二零一一年三月二十八日.出处:http://blog.csdn.net/v_JULY_v.声明:版权所有,侵权必究.----------------------------------- 引言: 目前国内图书市场上,抑或网上讲解红黑树的资料层次不齐,混乱不清,没有一个完整而统一的阐述.而本人的红黑树系列四篇文章(详见文末的参考文献),虽然从头至尾,讲的有根有据,层次清晰,然距离读者真正做到红黑树了然于胸,则还缺点什么. 而

红黑树的添加与删除

主脉络参考http://www.cnblogs.com/skywang12345/p/3245399.html#!comments 补图删除操作:https://blog.csdn.net/eson_15/article/details/51144079 R-B Tree的在线生成:http://sandbox.runjs.cn/show/2nngvn8w 数据结构与算法汇总:http://www.cnblogs.com/skywang12345/p/3603935.html 红黑树 R-B T