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

转载请注明出处:http://blog.csdn.net/mxway/article/details/38080315

下面维基百科上红黑树的5个性质

1.      节点是红色或黑色

2.      根是黑色

3.      所有叶子都是黑色(叶子是NIL节点)

4.      每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)

5.      从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

根据上面的5个性质,我们可以得出下面的结论:

结论1:在红黑树中若x只有一棵非空子树,则x必为黑色。

证明:假设x为红色,根据性质4可以推出x有两个黑色子节点。与x只有一棵非空子树矛盾。

结论2:在红黑树中若x只有一棵非空子树。则该非空子树的根必为红色,且该非空子树仅且只有一个根节点。

证明:假设y为x的左孩子,节点y的颜色为黑色,且y有子树。由于y是黑色,x的右子权为空,所以从x到其左子树各叶子结点的路径上黑色结点数大于x到其右子树叶到叶节点的路径上黑色节点数,违反性质5,所以节点y为红色。因为y为红色,如果y的子树存在,根据性质4可以得出y的两棵子树必为黑色。从x到经过y到各叶节点的路径上的黑色节点数大于到右子树叶节点路径上的黑色节点数。

同上所述,当y为x的右孩子时也可以证明结论2

下面讨论红黑树的删除问题:

1. 从上面的两个结论可以看出,如果要删除的节点只有一个孩子,那么直接用孩子节点的值代替父节点的值。删除子节点就可以,不需要进入删除调整算法。

2. 若当前要删除的节点两个孩子都不为空,此时我们只需要找到当前节点中序序列的后继节点。用后继节点的值替换当前节点的值。将后继节点作为新的当前节点,此时的当前节点一定只有一个右孩子或左右孩子都为空。

3. 通过步骤2后如果当前节点有后继节点,直接用其后继节点值替换当前节点值,不需要进入删除调整算法。如果当前节点没有后继节点,进入删除调整算法。

算法流程步骤:

1.      判断x的左右子树是否为空。

2.      如果x的左右子都不为空,找到中序序列中x的后继节点y,将x的值用y代替;将y作为新的x节点转到步骤1。否则转步骤3

3.      如果x的左子不空,将x的值用左子的值代替,删除x的左子,算法结束。否则转4

如果x的右子不空,将x的值用右子的值代替。

4.      如果x的右子不空,将x的值用右子的值代替,删除x的右子,算法结束。否则转5

5.      删除x,进入到红黑树删除节点调整程序。

下面通过图来详解红黑树的删除过程

首先利用上篇文章中的代码生成一棵红黑树,插入的顺序为:14,9,41,39,47,20,15,22,7,3,28,24

图1:红黑树

1.删除节点22,由于节点22只有一个孩子24,所以直接把22替换成24。根据上面的结论,不需要进行删除调整算法。

图2:删除节点22

2.删除节点24,24的节点颜色为黑色,且其兄弟39节点也为黑色,39的两个孩子为空,也为黑,所以将39结点染红,父节点28作为新的当前节点。由于28是红色,所以将28染黑,算法结束。

图3:删除节点24后的红黑树

3.删除节点39,因为39为叶节点,颜色为红。直接删除,不需要作任何调整。

图4:删除节点39后的红黑树

4.删除节点28,由于节点28是黑色,其兄弟节点47为黑,兄弟节点的两孩子也为黑。所以节点47染红。父节点41变当前节点

图5:删除节点28第一次调整

现在41为当前节点,由于41的兄弟节点14为黑,14的两个孩子也为黑。所以将14节点染红。父节点20也就是根节点为当前节点

图6:删除节点28第二次调整

此时20为当前节点,由于20是根节点调整算法结束,将28从红黑树中删除。

图7:删除节点28后的红黑树

至此红黑树的属性全部恢复

下面给出删除红黑树节点及调整的c++代码。关于红黑树删除调整算法可以看July的博客,他说的比较详细。这个代码是在上一篇 stl map底层之红黑树插入步骤详解与代码实现基础上增加的新功能

删除节点的c++程序。

template<typename T>
void RBTree<T>::DeleteValue(const T &v1)
{
	RBNode<T>		*p = NULL;
	RBNode<T>		*nextNode = NULL;
	Search(v1,p);
	if(p==NULL)
	{
		cout<<"删除的值不存在"<<endl;
		return;
	}
	if(p->left && p->right)
	{
		RBNode<T> *tempNode = p->right;
		while(tempNode)
		{//中序序列的后继节点
			nextNode = tempNode;
			tempNode = tempNode->left;
		}
		p->val = nextNode->val;
		p = nextNode;
	}
	if(p->left)
	{
		//直接用后继节点的值替换
		RBNode<T> *temp = p->left;
		p->val = temp->val;
		p->left = NULL;
		delete temp;
	}
	else if(p->right)
	{
		//直接用后继节点的值替换
		RBNode<T> *temp = p->right;
		p->val = temp->val;
		p->right = NULL;
		delete temp;
	}
	else
	{
		//左右子树都不存在,需要进入删除调整算法
		DeleteReblance(p);
		if(p==root)
		{
			root = NULL;
		}
		else if(p==p->parent->left)
		{//父节点的指针域需要修改
			p->parent->left = NULL;
		}
		else if(p==p->parent->right)
		{//父节点的指针域需要修改
			p->parent->right = NULL;
		}
		delete p;
	}
}

红黑树删除后调整算法:

template<typename T>
void RBTree<T>::DeleteReblance(RBNode<T> *node)
{
	RBNode<T> *parent = NULL;
	RBNode<T> *other = NULL;
	while(node->color==_rb_black_node && node->parent)
	{
		parent = node->parent;
		if(node == parent->left)
		{
			other = parent->right;
			if(other->color==_rb_red_node)
			{//情形1兄弟节点为红
				parent->color = _rb_red_node;
				other->color = _rb_black_node;
				_rbtree_rotate_left(parent);
				other = parent->right;
			}
			if( (other->left==NULL || other->left->color==_rb_black_node)
				&& (other->right==NULL || other->left->color==_rb_black_node))
			{//情形2兄弟为黑,且兄弟的两个孩子也为黑
				other->color=_rb_red_node;
				node = parent;
				continue;
			}
			if( other->right==NULL || other->right->color==_rb_black_node)
			{//情形3兄弟节点的右孩子为黑,左为红
				other->left->color=_rb_black_node;//此时左孩子一定存在且颜色为红,如果不满足就不会进入这个条件
				other->color = _rb_red_node;
				_rbtree_rotate_right(other);
				other = parent->right;
			}
			//情形4兄弟节点的右孩子为红
			other->right->color=_rb_black_node;
			other->color = parent->color;
			parent->color = _rb_black_node;
			_rbtree_rotate_left(parent);
			break;
		}
		else
		{
			other = parent->left;
			if(other->color==_rb_red_node)
			{//情形1兄弟节点为红
				parent->color = _rb_red_node;
				other->color = _rb_black_node;
				_rbtree_rotate_right(parent);
				other = parent->left;
			}
			if( (other->left==NULL || other->left->color==_rb_black_node)
				&& (other->right==NULL || other->left->color==_rb_black_node))
			{//情形2兄弟为黑,且兄弟的两个孩子也为黑
				other->color=_rb_red_node;
				node = parent;
				continue;
			}
			if( other->left==NULL || other->left->color==_rb_black_node)
			{//情形3兄弟节点的右孩子为黑,左为红
				other->right->color=_rb_black_node;//此时左孩子一定存在且颜色为红,如果不满足就不会进入这个条件
				other->color = _rb_red_node;
				_rbtree_rotate_left(other);
				other = parent->left;
			}
			//情形4兄弟节点的右孩子为红
			other->left->color=_rb_black_node;
			other->color = parent->color;
			parent->color = _rb_black_node;
			_rbtree_rotate_right(parent);
			break;
		}
	}
	node->color = _rb_black_node;
}
时间: 2024-10-12 20:24:39

一种新的删除红黑树节点的算法的相关文章

红黑树 节点的删除

接上一篇. 红黑树的插入操作! 红黑树的删除继续分各种情况进行考虑. 首先考虑红黑树的单支情况,即只有父节点只有一个子节点,另外一个为NULL,这样的话,只有一种情况,即父节点为黑色,子节点为红色,因为其他情况都会是孩子为黑色,因为孩子为红色父为红色,则与红父黑子矛盾.而当孩子是黑色时,另一个孩子是黑色的NULL,则必定使左右路径上黑色节点数量不等.所以单支只能为黑父红子. 这里的单支情况,是对任意一点的,若其只有一个孩子,则其必为黑色,孩子必为红色,且孩子为叶子节点.孩子为红色,如果有孙子,其

红黑树 结构内部算法解析

/** From CLR */ private void fixAfterInsertion(Entry<K,V> x) { x.color = RED; while (x != null && x != root && x.parent.color == RED) {//当前插入节点的父节点是 当前节点祖先节点的 左子节点 进入 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {//得到当前节点祖先节点的右子

算法导论 第13章 红黑树

二叉查找树的基本操作包括搜索.插入.删除.取最大和最小值等都能够在O(h)时间复杂度内实现,因此能在期望时间O(lgn)下实现,但是二叉查找树的平衡性在这些操作中并没有得到维护,因此其高度可能会变得很高,当其高度较高时,而二叉查找树的性能就未必比链表好了,所以二叉查找树的集合操作是期望时间O(lgn),最坏情况下为O(n). 红黑树也是一种二叉查找树,它拥有二叉查找树的性质,同时红黑树还有其它一些特殊性质,这使得红黑树的动态集合基本操作在最坏情况下也为O(lgn),红黑树通过给节点增加颜色和其它

java数据结构和算法06(红黑树)

这一篇我们来看看红黑树,首先说一下我啃红黑树的一点想法,刚开始的时候比较蒙,what?这到底是什么鬼啊?还有这种操作?有好久的时间我都缓不过来,直到我玩了两把王者之后回头一看,好像有点儿意思,所以有的时候碰到一个问题困扰了很久可以先让自己的头脑放松一下,哈哈! 不瞎扯咳,开始今天的正题: 前提:看红黑树之前一定要先会搜索二叉树 1.红黑树的概念 红黑树到底是个什么鬼呢?我最开始也在想这个问题,你说前面的搜索二叉树多牛,各种操作效率也不错,用起来很爽啊,为什么突然又冒出来了红黑树啊? 确实,搜索二

红黑树插入删除节点过程分析 &amp;&amp; C代码实现

红黑树的插入和删除规则: 红黑树的五个性质 1.    每个节点要么是红的,要么是黑的 2.    根节点时黑色的 3.    每个叶节点(叶节点既指树尾端NIL指针或NULL节点)是黑色的 4.    如果一个节点时红的,那么它的两个儿子都是黑色的 5.    对每个节点,其到叶节点树尾端NIL指针的每一条路径都包含相同数目的黑节点 这里所说的"叶节点"或者"NULL节点",它不包含数据而只充当树在此结束的知识. 二叉树的左旋和右旋这里不再讲解 红黑树的插入操作:

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

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

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

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

红黑树的插入与删除

红黑树(Red Black Tree) 是一种自平衡二叉查找树.红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能.红黑树可以在O(log n)时间内完成查找,插入和删除操作. 二叉搜索树可以看 二叉搜索树 AVL树可以看 AVL树的插入与删除 1. 红黑树的性质 红黑树的自平衡依赖于它的以下性质: 性质1. 结点是红色或黑色. 性质2. 根结点是黑色. 性质3. 每个结点节点(NIL结点,空结点,与其它二叉搜索树不同,红黑树将叶子结点的孩子

红黑树新解(删除)

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