rbtree插入算法分析

#include<iostream>
#include<queue>
using namespace std;

struct rbnode{
int key;
int color;//1=black,0=red;
struct rbnode *p,*left,*right;
rbnode(){}
rbnode(int k){key=k;
}
};
rbnode *nil;
bool RBinsert(rbnode **root,int k);
void LevelOrder(rbnode *t);
void RBinserFix(rbnode **root,rbnode *z);
void Left(rbnode **root, rbnode *x);
void Right(rbnode **root, rbnode *x);
void Left(rbnode **root, rbnode *x){
	if(x->right!=nil){
		rbnode * y=nil;
	y=x->right;
	x->right=y->left;
	if(y->left!=nil)y->left->p=x;
	y->p=x->p;
	if(x->p==nil) (*root)=y;
	else if(x==x->p->left) x->p->left=y;
	else x->p->right=y;
	y->left=x;
	x->p=y;}
}
void Right(rbnode **root, rbnode *x){
	if(x->left!=nil){
	rbnode * y=nil;
	y=x->left;
	x->left=y->right;
	if(y->right!=nil)y->right->p=x;
	y->p=x->p;
	if(x->p==nil) (*root)=y;
	else if(x==x->p->right) x->p->right=y;
	else x->p->left=y;
	y->right=x;
	x->p=y;
	}
}

void RBinserFix(rbnode **root,rbnode *z){
rbnode* y=nil;

	while(z!=*root&&z->p->color==0){
	if(z->p==z->p->p->left){
		y=z->p->p->right;
		if(y->color==0){
		z->p->color=1;
		y->color=1;
		z->p->p->color=0;
		z=z->p->p;
		}else 
		{		if(z==z->p->right){z=z->p;//LEFT
			Left(root,z);}
	z->p->color=1;
	z->p->p->color=0;
	//RightRotate();
	Right((root),z->p->p);
		}
		
	
	}else {
		y=z->p->p->left;
		if(y->color==0){
		z->p->color=1;
		y->color=1;
		z->p->p->color=0;
		z=z->p->p;
		}else 
		{		if(z==z->p->left){z=z->p;//LEFT
			Right(root,z);
			}
	z->p->color=1;
	z->p->p->color=0;
	//RightRotate();
	Left((root),z->p->p);}
	
	
	}
	

	}
	(*root)->color=1;

}
bool RBinsert(rbnode **root,int k){
	rbnode* z=new rbnode(k);
	
	//cout<<root->color;
	rbnode* y=nil;

	rbnode* x=*root;
while(x!=nil){
	y=x;
	if(k==x->key)return 0;
	if(k<x->key)x=x->left;
	else x=x->right;
}
	z->p=y;

	if(y==nil) {(*root)=z;(*root)->p=nil;}
else if(k<y->key) y->left=z;
		else y->right=z;
z->left=nil;z->right=nil;
z->color=0;
//LevelOrder(*root);
RBinserFix(root,z);
return 1;
}

void Visit(rbnode *t) {
	if (t) {
		cout << t->key;
		if(t->color)cout<<"黑 ";
		else cout<<"红 ";
	}
}

void LevelOrder(rbnode *t) {// 对* t逐层遍历
	queue<rbnode*> Q;
	while (t!=nil) {
		Visit(t); 
		if (t->left!=nil)
			Q.push(t->left);
		if (t->right!=nil)
			Q.push(t->right);
		if (Q.empty())
			break;
		t=Q.front();
		Q.pop();
	}
}


void main(){

//rbnode* root=
//root->color=1;//1=black
//root->p=nil;
//root->left=nil;root->right=nil;
rbnode** root=(rbnode**)malloc(sizeof(rbnode*));;
nil=new rbnode();
nil->color=1;
*root =nil;
//rbnode 
cout<<"输入操作类型:1插入元素 2输出结构 3删除节点 4退出"<<endl;
int sinin,num;
cin>>sinin;
while(sinin!=4)
{switch(sinin){
case 1:
	cout<<"插入: ";
	cin>>num;
	if(!RBinsert(root,num))cout<<"插入重复值"<<endl;
//	cout<<" root --key:"<<(*root)->p->color<<endl;

	break;
case 2:
	LevelOrder(*root);
	cout<<endl;
	break;
case 3:
	break;
}cout<<"输入操作类型:1插入元素 2输出结构 3删除节点 4退出"<<endl;
cin>>sinin;
}

}

插入算法基本思想:

红黑树每个节点由5个域组成:parent,leftchild,rightchild,key,color组成

插入过程分为两大部分,即1)插入到树中2)维持红黑树性质

1)根据节点key值,插入时P节点的左子树均小于该节点key值,右子树各节点均大于p节点的key值,根据这个特征,如果小于p的key就到p的左子树寻找,否则到p的右子树。

2)在插入一个节点到树中后,会引起不满足红黑树定义的变化,需要进行调节。调节方法有三种:1、调节颜色,2、左旋,3、右旋。不满足红黑树条件的原因是,插入时父节点为红色(或为根)。下图展示针对各种情况的旋转调节方法:

注:调节时先采用调节颜色的方法,且最对经过2次旋转达到平衡。

 

旋转过程中,二叉搜索树的性质保持不变

 

算法分析:

插入过程:小于节点值访问左子树,大于节点值访问右子树,否则返回插入失败O(logn)

调节过程:

void RBinserFix(T, z){

         while(colorp[z] ==RED){

//若z为根,则p[z]=nil[T],颜色为黑,不进入循环,p[z]为黑也不进入

         if(p[z] == left[p[p[z]]]){//z的父节点是祖父节点的左孩子

                   y= right[p[p[z]]];//y是z的叔叔,若为红色则调节颜色

                   if(color[y] ==RED){//改变颜色,case1

                            color[p[z]] =BLACK;

                            color[y]=BLACK;

                            color[p[p[z]]=RED;

                            z=p[p[z]];

                            }else //case2,3

                                      {  if(z==right[p[z]]){//case 2,左旋

z=p[z]; Left(root,z);

}

                                         Color[p[z]]=BLACK;//case3,右旋

                                        Color[p[p[z]]]=RED;

                                         Right((root),p[p[z]]);//p[z]为黑,退出

                           }

         }else {//对调上方“左”“右”, z的父节点是祖父节点的右孩子}

         }//endwhile

         Color[root[t]]=BLACK;

}

复杂程度为O(logn)

旋转过程(左旋):

Left(T,x)

{//假设right[x]!=nil[T]

Y=right[x] //记录指向y节点的指针,1

right[x]=left[y];p[left[y]]=x;// B连到X右,2

p[y]=p[x ];//修改parent指针,3

if(p[x]=nil[T])        //x是根

root[T]=y;          //修改树指针

else  if (x==left[p[x]]) left[p[x]]=y; //修改父节点孩子指针

else  right[p[x]]=y;

left[y]=x; p[x]=y;//x连接到y,4

}

复杂程度为O(1)

整个插入算法的时间是O(logn)

实验结果:

 

posted @ 2013-03-05 00:59  SONGHY  阅读(620)  评论(0编辑  收藏  举报