红黑树(RED-BLACK TREE)的插入和删除

24 篇文章 0 订阅
15 篇文章 0 订阅

        红黑树的插入和删除会需要用到旋转和颜色翻转。颜色翻转和旋转的主要目的是为了保证红黑树的5个性质,插入最直接来讲可能会导致根结点是红色(树为空),红色结点的子结点为红色,这是需要进行红黑调整以及子树翻转。删除最直接的结果就是删除了黑色结点,那么导致沿着该结点的路径上的黑色结点数目发生变化,此时需要翻转颜色和旋转子树来平衡。

红黑树的左旋和右旋


图1  左旋和右旋示意图


左旋的伪代码:

LEFT-ROTATE(T,x)
y = x.right
x.right = y.left
if y.left != nil(T)
	y.left.p = x
y.p = x.p
if x.p == nil(T)
	T.root = y
elseif x == x.p.left
	x.p.left = y
else x.p.right = y
y.left = x
x.p = y


代码很好理解,不用赘述,右旋可以参照给出,很简单。

红黑树的插入情况可以修改二叉查找树的插入函数完成插入,同理删除情况也是如此。

插入可能导致的情形及应对的策略有下面几种:


图2  插入的情形(一侧)

上述3种情形还有三种对称的情形。

删除的情形以及其应对的策略如下:


图3  删除的情形(一侧)

代码:

#include <iostream>
#include <assert.h>
#include <stack>
#include <queue>
#include <iomanip>
using namespace std;

#define BLACK 0
#define RED 1
typedef struct RBTreeNode* RBTree;
typedef struct RBTreeNode{
	int data;
	int color;
	RBTree lchild,rchild,parent;
} RBTreeNode ; 


RBTree createNode(int key)
{
	RBTree ptr = new RBTreeNode;
	ptr->data = key;
	ptr->parent = NULL;
	ptr->color = RED;
	ptr->lchild = NULL;
	ptr->rchild = NULL; 
	return ptr;
}

RBTree& grandparent(RBTree ptr)
{
	/* parameter n is short for node */
	return ptr->parent->parent;
}


RBTree uncle(RBTree n)
{
	/* parameter n is short for node */
	if ( n->parent == grandparent(n)->lchild)
		return grandparent(n)->rchild;
	else
		return grandparent(n)->lchild; 
}
RBTree minimum(RBTree ptr)
{
	while (ptr->lchild != NULL) {
		ptr = ptr->lchild;
	}
	return ptr;
}
RBTree succ(RBTree ptr)
{
	if (ptr->rchild != NULL)
		return minimum(ptr->rchild);
	/*RBTree y = n->parent;
	while (y != NULL && n == y->rchild){
		n = y;
		y = y->parent;
	}
	return y;*/
}

RBTree leftRotate(RBTree *T,RBTree x)
{
	/*
	           |
			   x
			  / \
			 #   y
				/ \
				# #
	*/
	RBTree y = NULL;
	RBTree root =NULL;
	y = x->rchild;

	x->rchild  = y->lchild;
	if (y->lchild != NULL) {
		y->lchild->parent = x;
	}

	
	y->parent = x->parent;
	if (x->parent == NULL)
	{
		root = y;// x = y?
	}
	else if (x->parent->lchild == x) 
		x->parent->lchild = y;
	else
		x->parent->rchild = y;
	y->lchild = x;
	x->parent = y;
	if (root)
		*T = root;
	return y;
}

RBTree rightRotate(RBTree *T,RBTree y)
{
	
	/*
	              |
			      y
			     / \
			    x   #
			   / \
			   # #
	*/

	RBTree x =NULL;
	x = y->lchild;
	RBTree root = NULL;

	y->lchild = x->rchild;

	if (NULL != x->rchild) {
		x->rchild->parent = y;
		cout<<"Runned?"<<endl;
	}

	if (y->parent != NULL)
		x->parent = y->parent;
	else
		x->parent = NULL;

	if ((y)->parent == NULL)
		root = x;
	else { 
		if (y->parent->rchild = y)
			y->parent->rchild = x;
		else 
			y->parent->lchild = x;
	}

	x->rchild = y;
	y->parent = x;
	if (root)
		*T = root;
	return  x;
}

void RBInsertFixup(RBTree *T,RBTree z)
{
	RBTree y;
	RBTree p;
	while ((p = z->parent) != NULL && p->color == RED)
	{
		if (p == grandparent(z)->lchild){
			/*  parent of z is the lef child of grand parent of z */
			y = uncle(z);
			if (y != NULL && y->color == RED){
				/* case 1 : color flip*/ 
				z->parent->color = BLACK;
				grandparent(z)->color = RED;
				y->color = BLACK;
				z = grandparent(z);
			} 
			else {
				if (z == z->parent->rchild) {
					/* case 2 */ 
					z = z->parent;
					leftRotate(T,z);
				}
				//* case 3*/ / 
				z->parent->color = BLACK;
				grandparent(z)->color = RED;
				rightRotate(T,z->parent->parent);
			}			
		}
		else {
			/* z->p = z->p->p->rchild */
			y = uncle(z);
			if (y != NULL && y->color == RED){
				/*case 4 */
				z->parent->color = BLACK;
				grandparent(z)->color = RED;
				y->color = BLACK;
				z = grandparent(z);
			} 
			else {
				if (z == z->parent->lchild) {
					/*case 5*/
					z = z->parent;
					rightRotate(T,z);
				}
				/*case 6*/
				z->parent->color = BLACK;
				grandparent(z)->color = RED;
				leftRotate(T,z->parent->parent);
			}
		}
	}
	(*T)->color = BLACK; 
} 

void RBDeleteFixup(RBTree *T,RBTree xp,RBTree x)
{
	/* xp is parent of x */
	RBTree w;
	while( x != *T && (x == NULL || x->color == BLACK))
	{
		if (x == xp->lchild){
			/* w is sibling of x */
			w = xp->rchild;
			if (w->color == RED){
				//case 1
				w->color = BLACK;
				x->parent->color = RED;
				leftRotate(T,x->parent);
				w = xp->rchild;
			}
			if ((w->lchild == NULL || w->lchild->color == BLACK) &&
				(w->rchild == NULL || w->rchild->color == BLACK)){
					//case 2
					w->color = RED;
					x = xp;
					xp = xp->parent;
			}
			else {
				if (w->rchild == NULL || w->rchild->color == BLACK){
					// case 3
					w->lchild->color = BLACK;
					w->color = RED;
					rightRotate(T,w);
					w = xp->rchild;
				}
				// case 4
				w->color = xp->color;
				xp->color = BLACK;
				w->rchild->color = BLACK;
				leftRotate(T,xp);
				x = *T;
			}
		}
		else {
			/* x == xp->rchild and  w is sibling of x*/
			w = xp->lchild;
			if (w->color == RED){
				//case 1
				w->color = BLACK;
				xp->color = RED;
				rightRotate(T,xp);
				w = xp->lchild;
			}
			if ((w->lchild == NULL || w->lchild->color == BLACK) &&
				(w->rchild == NULL || w->rchild->color == BLACK)){
					//case 2
					w->color = RED;
					x = xp;
					xp = xp->parent;
			}
			else {
				if (w->lchild == NULL || w->lchild->color == BLACK){
					// case 3
					w->rchild->color = BLACK;
					w->color = RED;
					leftRotate(T,w);
					w = xp->lchild;
				}
				// case 4
				w->color = xp->color;
				xp->color = BLACK;
				w->lchild->color = BLACK;
				rightRotate(T,xp);
				x = *T;
			}			
		}
	}
	if (x != NULL)
		x->color = BLACK;
}

void RBInsert(RBTree *T,int key)
{
	RBTree z = createNode(key);
	assert(z != NULL);

	RBTree y = NULL;
	RBTree x = *T;

	while (x != NULL) {
		y = x;
		if ( z->data < x->data)
			x = x->lchild;
		else if (z->data == x->data) {
			cout<<"Key = "<<z->data<<" is already in the RB-Tree."<<endl;
			delete z;
			return;
		}
		else {
			x = x->rchild;
		}			
	}

	z->parent = y;

	if (y == NULL) {
		*T = z;
	}
	else if (z->data < y->data) {
		y->lchild = z;
	}
	else {
		y->rchild = z;
	}
	z->lchild = NULL;
	z->rchild = NULL;
	z->color = RED;
	RBInsertFixup(T,z); 
} 


void RBDelete(RBTree *T,int key)
{
	RBTree z = *T;
	RBTree x,y;
	x = y = NULL;
	bool found = false;
	while ( z != NULL) {
		if (key < z->data)
			z = z->lchild;
		else if (key > z->data)
			z = z->rchild;
		else {
			found = true;
			break; 
		} 
	}

	if (!found) {
		cout<<"Key = "<<key<<" is not in the tree."<<endl;
		return;
	}
	/* copy data of y into z and delete y*/
	if (z->lchild == NULL || z->rchild == NULL)
		y = z;
	else
		y = succ(z);
	/* x will be subtree of y */
	if (y->lchild != NULL) {
		x = y->lchild;
	}
	else 
		/* is it ok? */
		x = y->rchild;

	/* x link to parent of y */	
	if (x != NULL)
		x->parent = y->parent;

	if(y->parent == NULL) {
		/* if y is the root of Tree */
		*T = x;
	}
	else if (y == y->parent->lchild) 
		y->parent->lchild = x;
	else 
		y->parent->rchild = x;
	if (y != z) {
		/* copy data of y into z */
		z->data = y->data;
	}
	if (y->color == BLACK)
		RBDeleteFixup(T,y->parent,x);
	delete y;
}

inline int max(int a,int b)
{
	return a>b?a:b;
}
int Height(RBTree T)
{
	if (T == NULL)
		return 0;
	else
		return 1 + max(Height(T->lchild), Height(T->rchild));
}
void MakeMat(RBTree T,int root_x,int root_y,int step,int **m)
{
	int lChildPos,rChildPos;
	lChildPos = root_x - step;
	rChildPos = root_x + step;
	if (T == NULL) 
		return;
	else
	{
		m[root_y][root_x] = 1;
		MakeMat(T->lchild,lChildPos,root_y+1,step>>1,m);
		MakeMat(T->rchild,rChildPos,root_y+1,step>>1,m);
	}
}

void RBTreeDisplay(RBTree T)
{
	if(T == NULL)
		return;
	/* init placehold flags m[h][len] */
	int h = Height(T);
	int len = (1<<h) - 1;
	int row = h; 
	int **m = new int*[row];
	for(int i= 0;i<row;i++){
		m[i] = new int[len];
		memset(m[i],0,len*sizeof(int));	
	}
	/* get level order traversal sequence */
	vector<RBTree> v;
	queue<RBTree> q;
	queue<RBTree> qt;
	q.push(T);
	RBTree pt;
	while(!q.empty())
	{
		pt = q.front();
		if (pt->lchild != NULL)
			q.push(pt->lchild);
		if(pt->rchild != NULL)
			q.push(pt->rchild);
		v.push_back(pt);		
		q.pop();
	}
	/* generate output matrix  plus '/' and '\\' m[2*h-1][len] */
	MakeMat(T,len>>1,0,len+1>>2,m);
	/* generate output */
	int cnt = 0;
	int width = 2;
	for(int i = 0; i < row; i++)
	{
		for(int j = 0; j < len; j++)
		{
			if(m[i][j])
			{
				cout<<((v[cnt])->color?'R':'B')<<":"<<(v[cnt])->data;
				cnt++;
			}
			else
				cout<<setw(width)<<' ';		
		}
		cout<<endl;
	}

}
int main()
{
	RBTree T = NULL;
	int i; 
	int a[] = {12,1,9,0,2,11,7};
	for (i = 0; i < 7; i++) {
		cout<<"Inserting key = "<<a[i]<<endl;
		RBInsert(&T,a[i]);
		RBTreeDisplay(T);
		cout<<endl;
		cout<<"----------------------------------------------------------"<<endl;;
	}
	cout<<"Inserting key = "<<2<<endl;
	RBInsert(&T,2);
	RBTreeDisplay(T);
	cout<<endl;
	cout<<"----------------------------------------------------------"<<endl;
	
	cout<<"Deleting key = "<<2<<endl;
	RBDelete(&T,2);
	RBTreeDisplay(T);
	cout<<endl;
	cout<<"----------------------------------------------------------"<<endl;
	
	cout<<"Deleting key = "<<7<<endl;
	RBDelete(&T,7);
	RBTreeDisplay(T);
	cout<<endl;
	cout<<"----------------------------------------------------------"<<endl;
	for (i = 0;i < 7;i++)
	{
		cout<<"Deleting key = "<<a[i]<<endl;
		RBDelete(&T,a[i]);
		RBTreeDisplay(T);
		cout<<endl;
		cout<<"----------------------------------------------------------"<<endl;
	}
}


测试结果:

Inserting key = 12
B:12

----------------------------------------------------------
Inserting key = 1
  B:12  
R:1    

----------------------------------------------------------
Inserting key = 9
  B:9  
R:1  R:12

----------------------------------------------------------
Inserting key = 0
      B:9      
  B:1      B:12  
R:0            

----------------------------------------------------------
Inserting key = 2
      B:9      
  B:1      B:12  
R:0  R:2        

----------------------------------------------------------
Inserting key = 11
      B:9      
  B:1      B:12  
R:0  R:2  R:11    

----------------------------------------------------------
Inserting key = 7
              B:9              
      R:1              B:12      
  B:0      B:2      R:11          
            R:7                

----------------------------------------------------------
Inserting key = 2
Key = 2 is already in the RB-Tree.
              B:9              
      R:1              B:12      
  B:0      B:2      R:11          
            R:7                

----------------------------------------------------------
Deleting key = 2
      B:9      
  R:1      B:12  
B:0  B:7  R:11    

----------------------------------------------------------
Deleting key = 7
      B:9      
  B:1      B:12  
R:0      R:11    

----------------------------------------------------------
Deleting key = 12
      B:9      
  B:1      B:11  
R:0            

----------------------------------------------------------
Deleting key = 1
  B:9  
B:0  B:11

----------------------------------------------------------
Deleting key = 9
  B:11  
R:0    

----------------------------------------------------------
Deleting key = 0
B:11

----------------------------------------------------------
Deleting key = 2
Key = 2 is not in the tree.
B:11

----------------------------------------------------------
Deleting key = 11

----------------------------------------------------------
Deleting key = 7
Key = 7 is not in the tree.

----------------------------------------------------------
REF:

1,算法导论 红黑树章节

2,http://chiyx.iteye.com/blog/1663013

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值