zoukankan      html  css  js  c++  java
  • 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)

    实验结果:

  • 相关阅读:
    中国石油昆仑加油卡
    157 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 02 异常内容简介
    156 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 01 Java常用工具类简介
    155 01 Android 零基础入门 02 Java面向对象 07 Java多态 07 多态知识总结 01 多态总结
    154 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 05 匿名内部类
    153 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 04 方法内部类
    152 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 03 静态内部类
    151 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 02 成员内部类
    150 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类概述 01 内部类概述
    149 01 Android 零基础入门 02 Java面向对象 07 Java多态 05 接口(重点)07 接口的继承
  • 原文地址:https://www.cnblogs.com/sunshinewill/p/2943657.html
Copyright © 2011-2022 走看看