首页 > 代码库 > 红黑树 节点的删除

红黑树 节点的删除

接上一篇。

红黑树的插入操作!


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

首先考虑红黑树的单支情况,即只有父节点只有一个子节点,另外一个为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 =http://www.mamicode.com/= x)break;>


我的红黑树代码!


红黑树 节点的删除