红黑树操作

红黑树操作

实验目的

通过插入操作建立一个红黑树,输入为1…n的数,同时将每次插入后的树信息打印出来。

 

实验原理

红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过对任何一条从根到叶子的简单路径上各个结点的颜色约束,红黑树确保没有一条路径比其他路径长出2倍,因而是近似于平衡的。

树中每个结点有五个属性:color,key,left,right和p;通过添加哨兵(T_nil)对红黑树的边界进行限定。

一棵红黑树是满足下面红黑性质的二叉搜索树:

(1)每个结点或是红色,或是黑色的;

(2)根节点是黑色的;

(3)每个叶节点(NIL)是黑色的;

(4)如果一个结点是红色的,则它的两个子节点都是黑色的;

(5)对每个结点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点;

 

实验过程

旋转操作:左旋和右旋

LEFT-ROTATE(T, x)

1 y = x.right

2 x.right = y.left

3 if y.left !=T.nil

4     y.left.p = x

5 y.p = x.p

6 if x.p == T.nil

7     T.root = y

8 elseif x ==x.p.left

9     x.p.left = y

10 else x.p.right= y

11 y.left = x

12 x.p = y

 

RIGHT-ROTATE(T, x)

1 y = x.left

2 x.left = y.right

3 if y.right !=T.nil

4     y.right.p = x

5 y.p = x.p

6 if x.p == T.nil

7     T.root = y

8 elseif x ==x.p.right

9     x.p.right = y

10 else x.p.left =y

11 y.right = x

12 x.p = y

 

插入操作:插入一个新节点就像在二叉树中插入一个结点一样,但是由于红黑树多了一个颜色属性,因此初始插入的结点的颜色属性为RED。选择将插入结点的颜色属性初始为RED的原因:在红黑树中插入一个结点时,如果初始插入结点的颜色为BLACK时,那么将会破坏性质(5),而且在修改性质(5)的过程中,需要去遍历每条路径,显然这是低效率的;如果将颜色初始为RED时,那么将会破坏性质(2)和性质(4),性质(2)修改很简单,性质(4)的修改过程只需要考虑叔叔结点的颜色,就可以逐步实现;显然在通过将插入结点初始为RED是更高效的操作。

RB-INSERT(T, z)

1 y = T.nil

2 x = T.root

3 while x != T.nil

4     y = x

5     if z.key < x.key

6     x = x.left

7     else x = x.right

8  z.p = y

9  if y == T.nil

10     T.root = z

11 elseif z.key< y.key

12     y.left = z

13 else y.right =z

14 z.left = T.nil

15 z.right = T.nil

16 z.color = RED

17RB-INSERT-FIXUP(T, z)

 

RB-INSERT-FIXUP(T,z)

1 while z.p.color== RED

2     if z.p == z.p.p.left

3         y = z.p.p.right

4         if y.color == RED

5             z.p.color = BLACK

6             y.color = BLACK

7             z.p.p.color = RED

8             z = z.p.p

9         else if z == z.p.right

10              z = z.p     

11              LEFT-ROTATE(T, z)

12        else

13            z.p.color = BLACK

14            z.p.p.color = RED

15            RIGHT-ROTATE(T, z.p.p)

16      else(same as then clause with “right” and“left” exchanged)

17     T.root.color = BLACK

 

实验总结

(一)在实验过程中,输入是通过调用一个struct node * creat_node(tree_pointerT, int key)来实现的,但是这种方法存在一个问题:使用malloc分配内存时,在最后没有进行free处理,容易造成内存泄漏;

(二)关于树的打印,实验主要关注的是红黑树算法代码的实现,所以没有过于的去关注数的可视性。说明一下如何理解打印下来的树,右端最突出的是根节点,下端是左子树,上端是右子树;,

(三)在整个实验过程中,由于自己基础较差,可能附录的代码中有多处注释,想了想还是没有删掉,也是一种实现算法的过程,以及如何去调试程序吧。

 

附录(代码)

#include <stdio.h>

#include <stdlib.h>

 

typedef  structnode *tree_pointer;

typedef struct node {

    int  key;

    char color;       //R represents red; B represents black

    tree_pointerp;

    tree_pointerleft;

    tree_pointerright;

} *tree_pointer;

 

void RB_insert(tree_pointer T_nil, tree_pointerT_root, tree_pointer z);

void left_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x);

void right_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x);

void RB_insert_fixup(tree_pointer T_nil, tree_pointerT_root, tree_pointer z);

void print_tree(tree_pointer T_root, int n);

 

 

int get_tree_height(tree_pointer T_root);

 

struct node * creat_node(tree_pointer T, int key);

 

 

int main(){

    inti,num,key,tree_height;

 

    tree_pointernew_node = NULL;

    tree_pointerT_root   = NULL;

    tree_pointerT_nil    = NULL;

    T_nil =(struct node *)malloc(sizeof(struct node));

    T_nil->color= 'B';

   

    T_root =(struct node *)malloc(sizeof(struct node));

//  T_root->key   = 11;

    T_root->color= 'B';

    T_root->p     = T_nil;

    T_root->left  = T_nil;

    T_root->right= T_nil;

 

    printf("T_nil= %p; key = %d; color = %c; p = %p; left = %p; right = %p\n",T_nil,T_nil->key, T_nil->color, T_nil->p, T_nil->left, T_nil->right);

    printf("T_root= %p; key = %d; color = %c; p = %p; left = %p; right = %p\n",T_root,T_root->key, T_root->color, T_root->p, T_root->left,T_root->right);

   

    printf("pleaseinput the number of nodes:");

    scanf("%d",&num);

    printf("pleaseinput the key:");

    scanf("%d",&key);

    T_root->key= key;

    printf("\n");

    tree_height =get_tree_height(T_root);

    print_tree(T_root,tree_height);

 

    printf("\n");

    for(i = 0; i< num-1; i++){

       printf("pleaseinput the key:");

       scanf("%d",&key);

       printf("\n");

       new_node =creat_node(T_nil, key);

       RB_insert(T_nil,T_root, new_node);

//     tree_height= get_tree_height(T_root);

//     print_tree(T_root,tree_height);

//     printf("\n666666666666666666666666\n");

    }

 

   

 

/*

    tree_pointernew1 = NULL;

    tree_pointernew2 = NULL;

    tree_pointernew3 = NULL;

    tree_pointernew4 = NULL;

    tree_pointernew5 = NULL;

//  T_root =creat_node(T_nil, 11);

    new1 =creat_node(T_nil, 2);

    new2 =creat_node(T_nil, 14);

    new3 =creat_node(T_nil, 1);

    new4 =creat_node(T_nil, 7);

    new5 =creat_node(T_nil, 15);

   

 

   

    RB_insert(T_nil,T_root, new1);

    RB_insert(T_nil,T_root, new2);

    RB_insert(T_nil,T_root, new3);

    RB_insert(T_nil,T_root, new4);

    RB_insert(T_nil,T_root, new5);

 

    printf("%p,  %p   %p",new1->p,new1->left,new1->right);

    new1 = new2;

 

    printf("\n1111111111111111111111111\n");

    printf("new1= %p; key = %d; color = %c;",new1,new1->key,new1->color);

    printf("p=%p; left = %p; right = %p\n",new1->p,new1->left,new1->right);

 

    printf("new2= %p; key = %d; color = %c; p = %p; left = %p; right = %p\n",new2,new2->key, new2->color, new2->p, new2->left, new2->right);

*/

//  tree_height =get_tree_height(T_root);

//  print_tree(T_root,tree_height);

   

}

 

struct node * creat_node(tree_pointer T, int key){

    tree_pointernew = NULL;

    new = (structnode *)malloc(sizeof(struct node));

    new->key   = key;

    new->color= 'R';

    new->p     = T;

    new->left  = T;

    new->right= T;

    return new;

}

 

void RB_insert(tree_pointer T_nil, tree_pointerT_root, tree_pointer z){

    tree_pointerx = NULL;

    tree_pointery = NULL;

    y = T_nil;

    x = T_root;

 

//  printf("\nnowRB_insert is running!\n");

 

    while(x !=T_nil){

       y = x;

       if(z->key< x->key)

           x =x->left;

       else

           x =x->right;

    }

 

    z->p = y;

    if(y ==T_nil)

       T_root   = z;

    elseif(z->key < y->key)

       y->left  = z;

    else

       y->right= z;

   

    z->left  = T_nil;

    z->right =T_nil;

    z->color ='R';

 

   

 

    RB_insert_fixup(T_nil,T_root, z);

 

//  printf("\nnowRB_insert is over!\n");

}

 

void RB_insert_fixup(tree_pointer T_nil, tree_pointerT_root, tree_pointer z){

    tree_pointery = NULL;

 

//  printf("\nnowRB_insert_fixup is running!\n");

   

    while(z->p->color== 'R'){

       if(z->p== z->p->p->left){

           y =z->p->p->right;

          

           if(y->color== 'R'){

              z->p->color    = 'B';

              y->color       = 'B';

              z->p->p->color= 'R';

              z =z->p->p;

           }

           elseif(z == z->p->right){

              z =z->p;

              left_rotate(T_nil,T_root, z);

           }

           else{

              z->p->color    = 'B';

              z->p->p->color= 'R';

              right_rotate(T_nil,T_root, z->p->p);

             

           }

       }

       //

       elseif(z->p = z->p->p->right){

           y =z->p->p->left;

 

           if(y->color== 'R'){

              z->p->color    = 'B';

              y->color       = 'B';

              z->p->p->color= 'R';

              z =z->p->p;

           }

           elseif(z == z->p->left){

              z =z->p;

              right_rotate(T_nil,T_root, z);

           }

           else{

              z->p->color    = 'B';

              z->p->p->color= 'R';

              left_rotate(T_nil,T_root, z->p->p);

           }

       }

       T_root->color= 'B';

    }

 

//  printf("\nnowRB_insert_fixup is over!\n");

    inttree_height;

    if(T_root->p== T_nil){

       tree_height= get_tree_height(T_root);

       print_tree(T_root,tree_height);

    }

    else{

       tree_height= get_tree_height(T_root);

       print_tree(T_root->p,tree_height);

    }

}

 

 

void left_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x){

    tree_pointery = NULL;     

    y =x->right;

   

    x->right =y->left;

    if(y->left!= T_nil)

       y->left->p= x;

 

    y->p =x->p;

    if(x->p ==T_nil)

       T_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_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x){

    tree_pointery = NULL;

    y =x->left;

 

    x->left =y->right;

    if(y->right!= T_nil)

       y->right->p= x;

   

    y->p =x->p;

    if(x->p ==T_nil)

       T_root =y;

    else if(x ==x->p->right)

       x->p->right= y;

    else

       x->p->left= y;

   

    y->right =x;

    x->p = y;

}

 

int get_tree_height(tree_pointer T_root){

    if(!T_root)

       return 0;

    intleft_height,right_height;

    left_height  = get_tree_height(T_root->left);

    right_height= get_tree_height(T_root->right);

    return(left_height < right_height)?(right_height+1):(left_height+1);

}

 

void print_tree(tree_pointer T_root, int n){

    int i;

    if(T_root ==NULL)

       return;

    print_tree(T_root->right, n-1);

 

    for(i = 0; i< n-1; i++)

       printf("   ");

    if(n > 0){

       printf("---");

       printf("%d(%c)\n",T_root->key,T_root->color);

    }

   

    print_tree(T_root->left,n-1);

}

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值