zoukankan      html  css  js  c++  java
  • 红黑树入门

        红黑树 (参看《算法导论》)

      红黑树是一种平衡二叉树,巧妙地利用结点颜色来简化维护平衡的难度。具有如下性质:

      1.红黑树上所有结点要么是红色的,要么是黑色的。

      2.红黑树的根节点是黑色的。

      3.如果一个结点是红色的,那么他的两个子结点必须是黑色的。

      4.对于每一个结点,他左子树的黑色结点数量必然等于右子树的黑色结点数量。

      5.所有叶子结点必然是黑色的。

      (一)抛弃原有的NULL,所有指向NULL的指针,改为指向一个与普通结点相同的T.null结点,T.null结点颜色固定为黑色,这样便解决了叶子结点的问题,同时根结点的父指针也指向它。

      (二)每次新插入结点为红色,这样不影响性质1、4、5,也就是说当插入结点时,只可能影响到性质2或者3,维护起来方便,可以向上维护,(插入结点设为x),如果x为根结点,那么可以直接改成黑色,如果不是,那么判断父结点是不是红色,如果是,说明违背了性质3,可以通过旋转、上升矛盾(直至根)来解决。

      (三)删除一个结点,寻找替代的结点,也就是后继,将这个替代点改成与原要删除的点一样的颜色,这么,问题就缩小到替代点原位置可能少了一个黑结点,那么可以通过上升矛盾子树(即令与他相对应的兄弟子树也少一个黑结点,那么便变成父结点所在的子树少了一个黑结点)或者红转黑来解决,需要注意的是不要在维护过程中,违背更多的红黑树性质。

      

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<string.h>
      4 
      5 #define RED 0
      6 #define BLACK 1
      7 
      8 typedef struct node
      9 {
     10   bool color;   //结点颜色,红色或者黑色
     11   int data;     //数据存放
     12   struct node *fa,*lchild,*rchild; //三个指针
     13 }RB_Node;
     14 
     15 typedef struct
     16 {
     17   RB_Node *root; //指向树的根节点
     18   RB_Node *null; //在红黑树中用来代替NULL,方便编程
     19 }Tree;
     20 
     21 Tree *Tree_Init()
     22 {
     23   Tree *T;
     24   T=(Tree *)malloc(sizeof(Tree));
     25   T->null=(RB_Node *)malloc(sizeof(RB_Node));
     26   T->null->color=BLACK;
     27   T->null->lchild=T->null;
     28   T->null->rchild=T->null;
     29   T->null->fa=T->null;
     30   T->root=T->null;
     31   return T;
     32 }
     33 
     34 RB_Node *Node_Init(Tree *T)
     35 {
     36   RB_Node *s;
     37   s=(RB_Node *)malloc(sizeof(RB_Node));
     38   s->color=RED;
     39   s->lchild=T->null;
     40   s->rchild=T->null;
     41   s->fa=T->null;
     42   return s;
     43 }
     44 
     45 void RB_Left_Rotate(Tree *T,RB_Node *x) //左旋转,原本为  (x在上),旋转为 /(x在下)
     46 {
     47   RB_Node *y=x->rchild;
     48   x->rchild=y->lchild;
     49   y->lchild->fa=x;
     50   if(x==T->root) T->root=y;
     51   else
     52   {
     53     if(x==x->fa->lchild) x->fa->lchild=y;
     54     else x->fa->rchild=y;
     55   }
     56   y->fa=x->fa;
     57   y->lchild=x;
     58   x->fa=y;
     59 }
     60 
     61 void RB_Right_Rotate(Tree *T,RB_Node *x) //右旋转,原本为 / (x在上),旋转为 (x在下)
     62 {
     63   RB_Node *y=x->lchild;
     64   x->lchild=y->rchild;
     65   y->rchild->fa=x;
     66   if(x==T->root) T->root=y;
     67   else
     68   {
     69     if(x==x->fa->lchild) x->fa->lchild=y;
     70     else x->fa->rchild=y;
     71   }
     72   y->fa=x->fa;
     73   y->rchild=x;
     74   x->fa=y;
     75 }
     76 
     77 void RB_Adjust_Insert(Tree *T,RB_Node *x)
     78 {
     79   while(x->fa->color==RED)
     80   {
     81     if(x->fa==x->fa->fa->lchild)
     82     {
     83       RB_Node *y=x->fa->fa->rchild;
     84       if(y->color==RED)
     85       {
     86         y->color=BLACK;
     87         x->fa->color=BLACK;
     88         x->fa->fa->color=RED;
     89         x=x->fa->fa;
     90       }
     91       else if(x==x->fa->rchild)
     92       {
     93         x=x->fa;
     94         RB_Left_Rotate(T,x);
     95       }
     96       else
     97       {
     98         x->fa->fa->color=RED;
     99         x->fa->color=BLACK;
    100         RB_Right_Rotate(T,x->fa->fa);
    101       }
    102     }
    103     else
    104     {
    105       RB_Node *y=x->fa->fa->lchild;
    106       if(y->color==RED)
    107       {
    108         y->color=BLACK;
    109         x->fa->color=BLACK;
    110         x->fa->fa->color=RED;
    111         x=x->fa->fa;
    112       }
    113       else if(x==x->fa->lchild)
    114       {
    115         x=x->fa;
    116         RB_Right_Rotate(T,x);
    117       }
    118       else
    119       {
    120         x->fa->fa->color=RED;
    121         x->fa->color=BLACK;
    122         RB_Left_Rotate(T,x->fa->fa);
    123       }
    124     }
    125   }
    126   T->root->color=BLACK;
    127 }
    128 
    129 void RB_Insert(Tree *T,RB_Node *x)
    130 {
    131   //新插入结点显红色,可以在函数外面写
    132   RB_Node *p=T->root,*q;
    133   if(p==T->null)
    134   {
    135     T->root=x;
    136     x->color=BLACK;
    137     return ;
    138   }
    139   while(p!=T->null)
    140   {
    141     q=p;
    142     if(x->data>=p->data) p=p->rchild;
    143     else p=p->lchild;
    144   }
    145   if(x->data>=q->data) q->rchild=x;
    146   else q->lchild=x;
    147   x->fa=q;
    148   RB_Adjust_Insert(T,x);
    149 }
    150 
    151 RB_Node *RB_Search_MinMum(Tree *T,RB_Node *x)
    152 {
    153   while(x->lchild!=T->null)
    154   {
    155     x=x->lchild;
    156   }
    157   return x;
    158 }
    159 
    160 void RB_Transplant(Tree *T,RB_Node *u,RB_Node *v)
    161 {
    162   if(u->fa==T->null) T->root=v;
    163   else if(u->fa->lchild==u) u->fa->lchild=v;
    164   else u->fa->rchild=v;
    165   v->fa=u->fa;
    166 }
    167 
    168 void RB_Adjust_Delete(Tree *T,RB_Node *x)
    169 {
    170   while(x!=T->root&&x->color==BLACK)
    171   {
    172     if(x==x->fa->lchild)
    173     {
    174       RB_Node *w=x->fa->rchild;
    175       if(w->color==RED)
    176       {
    177         w->color=BLACK;
    178         x->fa->color=RED;
    179         RB_Left_Rotate(T,x->fa);
    180         w=x->fa->rchild;
    181       }
    182       else if(w->lchild->color==BLACK&&w->rchild->color==BLACK)
    183       {
    184         w->color==RED;
    185         x=x->fa;
    186       }
    187       else if(w->rchild->color==BLACK)
    188       {
    189         w->lchild->color=BLACK;
    190         w->color=RED;
    191         RB_Right_Rotate(T,w);
    192         w=x->fa->rchild;
    193       }
    194       else
    195       {
    196         w->color=x->fa->color;
    197         x->fa->color=BLACK;
    198         w->rchild->color=BLACK;
    199         RB_Left_Rotate(T,x->fa);
    200         x=T->root;
    201       }
    202     }
    203     else
    204     {
    205       RB_Node *w=x->fa->lchild;
    206       if(w->color==RED)
    207       {
    208         w->color=BLACK;
    209         x->fa->color=RED;
    210         RB_Right_Rotate(T,x->fa);
    211         w=x->fa->lchild;
    212       }
    213       else if(w->lchild->color==BLACK&&w->rchild->color==BLACK)
    214       {
    215         w->color=RED;
    216         x=x->fa;
    217       }
    218       else if(w->lchild->color==BLACK)
    219       {
    220         w->rchild->color=BLACK;
    221         w->color=RED;
    222         RB_Left_Rotate(T,w);
    223         w=x->fa->lchild;
    224       }
    225       else
    226       {
    227         w->color=x->fa->color;
    228         x->fa->color=BLACK;
    229         w->lchild->color=BLACK;
    230         RB_Right_Rotate(T,x->fa);
    231         x=T->root;
    232       }
    233     }
    234   }
    235   x->color=BLACK;
    236 }
    237 
    238 void RB_Delete(Tree *T,RB_Node *z)
    239 {
    240   RB_Node *y=z,*x;
    241   bool y_original_color=y->color;
    242   if(z->lchild==T->null)
    243   {
    244     x=z->rchild;
    245     RB_Transplant(T,z,z->rchild);
    246     free(z);
    247   }
    248   else if(z->rchild==T->null)
    249   {
    250     x=z->lchild;
    251     RB_Transplant(T,z,z->lchild);
    252     free(z);
    253   }
    254   else
    255   {
    256     y=RB_Search_MinMum(T,z->rchild);
    257     y_original_color=y->color;
    258     x=y->rchild;
    259     if(y->fa==z)
    260       x->fa=y;  //等会要从x处开始调整,如果x为T->null,那么现在先预置T->null的父结点为y
    261     else
    262     {
    263       RB_Transplant(T,y,y->rchild);
    264       y->rchild=z->rchild;
    265       y->rchild->fa=y; //也有上面x->fa=y;的效果
    266     }
    267     RB_Transplant(T,z,y);
    268     y->lchild=z->lchild;
    269     y->lchild->fa=y;
    270     y->color=z->color;
    271     free(z);
    272   }
    273   if(y_original_color==BLACK)
    274     RB_Adjust_Delete(T,x);
    275 }
    276 
    277 void RB_Display_Tree(Tree *T,RB_Node *p,int floor=0)
    278 {
    279   if(p==T->null) return;
    280   RB_Display_Tree(T,p->lchild,floor+1);
    281   for(int i=0;i<floor;i++)
    282     printf(" ");
    283   printf("%d %s
    ",p->data,p->color==BLACK?"BLACK":"RED");
    284   RB_Display_Tree(T,p->rchild,floor+1);
    285 }
    286 
    287 RB_Node *RB_Search(Tree *T,int data)      //找到第一个,如果没有,返回T->null
    288 {
    289   RB_Node *p=T->root;
    290   while(p!=T->null)
    291   {
    292     if(p->data==data) return p;
    293     if(data>p->data) p=p->rchild;
    294     else p=p->lchild;
    295   }
    296   return T->null;
    297 }
    298 
    299 void RB_Clear(Tree *T,RB_Node *x)
    300 {
    301   if(x!=T->null)
    302   {
    303     RB_Clear(T,x->lchild);
    304     RB_Clear(T,x->rchild);
    305     free(x);
    306   }
    307 }
    308 
    309 void CE_SHI()   //用于测试红黑树
    310 {
    311   Tree *T;
    312   T=Tree_Init();
    313   while(1)
    314   {
    315     printf("
    --------红黑树---------------
    ");
    316     printf("1. 添加结点
    ");
    317     printf("2. 删除结点
    ");
    318     printf("0. 退出
    ");
    319     int ch;
    320     scanf("%d",&ch);
    321     if(ch==1)
    322     {
    323       printf("请输入关键字:");
    324       scanf("%d",&ch);
    325       RB_Node *x;
    326       x=Node_Init(T);
    327       x->data=ch;
    328       RB_Insert(T,x);
    329       RB_Display_Tree(T,T->root);
    330     }
    331     else if(ch==2)
    332     {
    333       printf("请输入关键字:");
    334       scanf("%d",&ch);
    335       RB_Node *x=RB_Search(T,ch);
    336       RB_Delete(T,x);
    337       RB_Display_Tree(T,T->root);
    338     }
    339     else if(ch==0)
    340     {
    341       RB_Clear(T,T->root);
    342       T->root=T->null;
    343     }
    344     system("pause");
    345     system("cls");
    346     RB_Display_Tree(T,T->root);
    347   }
    348   free(T);
    349 }
    350 
    351 int main()
    352 {
    353   CE_SHI();
    354   return 0;
    355 }
  • 相关阅读:
    Oracle使用笔记
    跳转至锚点
    项目中使用到的AOP
    短信验证码接口使用
    阿里人脸识别接口
    java实现网页截图
    java后台接收微信服务号/订阅号消息
    java 实现redis缓存
    redis 常用命令
    被骗了,自己还不知道
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5003603.html
Copyright © 2011-2022 走看看