zoukankan      html  css  js  c++  java
  • 红黑树 (洛谷 P3369 【模板】普通平衡树 )

    (以前学习的红黑树,在今天写算法大作业的时候用到了,哈哈, 即使研究生也要继续学习算法呀)

    红黑树的五条性质:

      1) 节点颜色为红色或黑色

      2) 根节点为黑色

      3) 每一个叶子节点两个NIL节点也为黑色

      4) 红色节点后继为黑色

      5) 从根节点到叶子节点简单路径黑高相同

    红黑树是一颗自平衡的二叉查找树, 查询,插入,删除的时间复杂度都为O(logn)

    红黑树简直就是一棵神奇的数据结构~~~~~~~~,我很想知道他们的灵感从哪里来的. 据说红黑树是2-3树的变形, RNtree的插入操作类比2-3树我还可以理解.

    但BRtree那个删除操作真的好简洁于奇妙~~向这些科学家致敬!!

     总结一下:

           (1)  插入节点z默认时红色,   可能违反的性质:
                1)  z的parent节点颜色是红色
                2)  根节点是红色

         插入时关键要看叔叔节点

         (2)  删除节点y,并且用x节点代替,可能违反的性质

               1)  经过x的路径,黑高减1
               2) x的为红色,x的parent也是红
               3) x为根节点,颜色为红色

        删除时要看兄弟节点

    代码的逻辑时根据算法导论的逻辑写出, 并且经过洛谷P3369习题验证

    (这是我提交过的最长代码.....

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define RED 1
      4 #define BLACK 0
      5 #define RBnode node<T> *
      6 
      7 template <class T>
      8 struct node {
      9     T key;
     10     int sum; //sum子树节点数
     11     bool color;
     12     node *p, *left, *right;
     13     node() {
     14         sum = 0; color = BLACK;
     15     }
     16     node(T key, int sum, int color, node *p, node *left, node *right) :
     17         key(key), sum(sum), color(color), p(p), left(left), right(right) {}
     18     void up() {
     19         sum = 1 + left->sum + right->sum; // nil节点不更新
     20     }
     21 };
     22 
     23 template <class T>
     24 class  RBtree {
     25 private:
     26     RBnode rt;
     27     RBnode nil;
     28 public:
     29     RBtree() {
     30         nil = new node<T>();
     31         nil->p = nil->left = nil->right = nil;
     32         rt = nil;
     33     }
     34 
     35     void mid_print(RBnode x) { // 中序遍历
     36         if (x == nil) return;
     37         mid_print(x->left);
     38         cout << "key: " << x->key << " color:" << x->color << " sum: " << x->sum << endl;
     39         mid_print(x->right);
     40     }
     41 
     42     void  my_print() {
     43         mid_print(rt);
     44     }
     45 
     46     void insert(T key) {
     47         RBnode z = new node<T>(key, 1, RED, nil, nil, nil);
     48         RBnode y = nil; // y: x的parent;
     49         RBnode x = rt;
     50         while (x != nil) {
     51             y = x;
     52             if (z->key <= x->key)
     53                 x = x->left;
     54             else
     55                 x = x->right;
     56         }
     57         z->p = y;  // 特别的根节点父节点是nil
     58         if (y == nil)
     59             rt = z;
     60         else if (z->key <= y->key)
     61             y->left = z;
     62         else
     63             y->right = z;
     64         // sum的改变
     65         while (y != nil) {
     66             y->up();
     67             y = y->p;
     68         }
     69         insert_fixup(z);
     70     }
     71 
     72     // 可能违反的性质:
     73     // 1)z的parent节点颜色是红色
     74     // 2)根节点是红色 
     75     void insert_fixup(RBnode z) {  // 插入看叔叔节点 
     76         while (z->p->color == RED) {
     77             if (z->p == z->p->p->left) {
     78                 RBnode uncle = z->p->p->right;
     79                 if (uncle->color == RED) { // case1 叔叔节点是红色; 叔叔和父亲加一层黑色,祖父层变黑(黑色上移)
     80                     z->p->color = BLACK;
     81                     uncle->color = BLACK;
     82                     z->p->p->color = RED;
     83                     z = z->p->p;
     84                 }
     85                 else {
     86                     if (z->p->right == z) { // case2 叔叔是黑色, 祖孙三代不在一条直线, 调整到case3 
     87                         z = z->p;
     88                         left_rotate(z);
     89                     }
     90                     z->p->color = BLACK;  // case3 调整过后,冲突解决
     91                     z->p->p->color = RED;
     92                     right_rotate(z->p->p);
     93                 }
     94             }
     95             else {
     96                 RBnode uncle = z->p->p->left;
     97                 if (uncle->color == RED) { // case1
     98                     z->p->color = BLACK;
     99                     uncle->color = BLACK;
    100                     z->p->p->color = RED;
    101                     z=z->p->p;
    102                 }
    103                 else {
    104                     if (z->p->left == z) { // case 2
    105                         z = z->p;
    106                         right_rotate(z);
    107                     }
    108                     z->p->color = BLACK;  // case 3
    109                     z->p->p->color = RED;
    110                     left_rotate(z->p->p);
    111                 }
    112             }
    113         }
    114         rt->color = BLACK;
    115     }
    116 
    117     // 旋转的性质: 左旋或右旋后,交换两节点的颜色不改变黑高(自我总结)
    118     void left_rotate(RBnode x) {
    119         RBnode y = x->right;
    120         x->right = y->left;
    121         if (y->left != nil)
    122             y->left->p = x;
    123         y->p = x->p;
    124         if (x->p == nil)
    125             rt = y;
    126         else if (x->p->left == x)
    127             x->p->left = y;
    128         else
    129             x->p->right = y;
    130         y->left = x;
    131         x->p = y;
    132         if (x!=nil) x->up(); // 先调整x,再调整y
    133         if (y!=nil) y->up();
    134     }
    135 
    136     void right_rotate(RBnode x) {
    137         RBnode y = x->left;
    138         x->left = y->right;
    139         y->p = x->p;
    140         if (y->right != nil)
    141             y->right->p = x;
    142         if (x->p == nil)
    143             rt = y;
    144         else if (x->p->left == x)
    145             x->p->left = y;
    146         else
    147             x->p->right = y;
    148         y->right = x;
    149         x->p = y;
    150         if (x!=nil) x->up();
    151         if (x!=nil) y->up();
    152     }
    153 
    154     RBnode min_mum(RBnode x) {
    155         while (x->left != nil)
    156             x = x->left;
    157         return x;
    158     }
    159 
    160     RBnode max_mum(RBnode x) {
    161         while (x->right != nil)
    162             x = x->right;
    163         return x;
    164     }
    165 
    166     RBnode low_find(int k) { // 寻找比k小且最大的节点
    167         return _low(k,rt);
    168     }
    169 
    170     RBnode _low (int k, RBnode x) {
    171         if (x==nil) return x;
    172         if (k<=x->key) return _low(k,x->left);
    173         else {
    174             RBnode ans=_low(k,x->right);
    175             if (ans!=nil) return ans;
    176             else          return x;
    177         }
    178     }
    179 
    180     RBnode upp_find(T k) { // 寻找比k大且最小的节点
    181         return _upp(k,rt);
    182     }
    183 
    184     RBnode _upp (T k, RBnode x) {
    185         if (x==nil) return x;
    186         if (k>=x->key) return _upp(k,x->right);
    187         else {
    188             RBnode ans=_upp(k,x->left);
    189             if (ans!=nil) return ans;
    190             else          return x;
    191         }
    192     }
    193 
    194     RBnode rfind(T key) {  // 相等元素的最后一个节点
    195         RBnode x = rt;
    196         while (x != nil) {
    197             if (key<x->key)
    198                 x = x->left;
    199             else if (key>x->key)
    200                 x = x->right;
    201             else
    202                 return x;
    203         }
    204         return x;
    205     }
    206 
    207     RBnode find(T key) {  // 相等元素第一个节点
    208         return my_find(key, rt);
    209     }
    210 
    211     RBnode my_find(T key, RBnode x) {
    212         if (x == nil) return nil;
    213         if (key<x->key) return my_find(key, x->left);
    214         if (key == x->key) {
    215             RBnode ans = my_find(key, x->left);
    216             if (ans == nil) return x;
    217             else          return ans;
    218         }
    219         return my_find(key, x->right);
    220     }
    221 
    222     RBnode find_kth(int k) {  // 排名第k的元素, 相等的元素具有不同的排名
    223         RBnode x = rt;
    224         if (rt->sum<k) return nil;
    225         while (k != x->left->sum + 1) {
    226             if (k <= x->left->sum)
    227                 x = x->left;
    228             else {
    229                 k -= x->left->sum + 1;
    230                 x = x->right;
    231             }
    232         }
    233         return x;
    234     }
    235 
    236     int get_rank(RBnode x) { // 寻找节点x的排名
    237         RBnode t=rt; int k=0;
    238         while (t!=x) {
    239             if (x->key<=t->key)
    240                 t=t->left;
    241             else  {
    242                 k+=t->left->sum+1;
    243                 t=t->right;                
    244             }
    245         }
    246         return k+t->left->sum+1;
    247     }
    248 
    249     void transplate(RBnode y, RBnode x) {  // 以节点x代替y,但不对y的子节点经行替换
    250         if (y->p == nil)
    251             rt = x;
    252         else if (y->p->left == y)
    253             y->p->left = x;
    254         else
    255             y->p->right = x;
    256         x->p = y->p;
    257     }
    258 
    259     void remove(RBnode z) {  // y: 要删除的节点  x: 代替的节点
    260         RBnode y = z;
    261         RBnode x;
    262         int ycolor = y->color;
    263         if (y->left == nil) {
    264             x = y->right;
    265             transplate(y, x);
    266         }
    267         else if (y->right == nil) {
    268             x = y->left;
    269             transplate(y, x);
    270         }
    271         else {
    272             y = min_mum(y->right);
    273             ycolor = y->color;
    274             x = y->right;
    275             if (y->p == z)
    276                 x->p = y;  // x可能是nil节点,因此需要记录其父亲
    277             else {
    278                 transplate(y, x);
    279                 y->right = z->right;
    280                 z->right->p = y;
    281             }
    282             transplate(z,y);
    283             y->left = z->left;
    284             z->left->p = y;
    285             y->color = z->color; // y代替z,但颜色不改变!!!!!!
    286             y = z;  // y指向废弃节点
    287         }
    288         if (ycolor == BLACK)
    289             remove_fixup(x);
    290         RBnode t=x->p; // 最后调整sum
    291         while (t!=nil) { 
    292             t->up();
    293             t=t->p;
    294         }
    295         delete y;
    296     }
    297 
    298     // 可能有冲突:
    299     // 1)经过x的路径,黑高减1
    300     // 2)x的为红色,x的parent也是红
    301     // 3)x为根节点,颜色为红色
    302     void remove_fixup(RBnode x) { // 看兄弟节点 // 减少x多的一重黑色
    303         while (x != rt&&x->color == BLACK) {
    304             if (x == x->p->left) {
    305                 RBnode bro = x->p->right;
    306                 if (bro->color == RED) { // case1 兄弟节点为红色,转化为情况234 
    307                     bro->color = BLACK;
    308                     bro->p->color = RED;
    309                     left_rotate(x->p);
    310                     bro = x->p->right;
    311                 }
    312                 if (bro->left->color == BLACK&&bro->right->color == BLACK) { // case2 兄弟节点及其儿子节点都为黑色
    313                     bro->color = RED;
    314                     x = x->p;
    315                 }
    316                 else {
    317                     if (bro->right->color == BLACK) { // case3 兄弟右节点不为红色
    318                         bro->color = RED;
    319                         bro->left->color = BLACK;
    320                         right_rotate(bro);
    321                         bro = x->p->right;
    322                     }
    323                     bro->right->color = BLACK; //case4   兄弟右孩子节点为红色,调整之后结束循环
    324                     bro->color = bro->p->color;
    325                     bro->p->color = BLACK;
    326                     left_rotate(x->p);
    327                     x = rt; // 终止递归
    328                 }
    329             }
    330             else {
    331                 RBnode bro = x->p->left;
    332                 if (bro->color == RED) { // case 1
    333                     bro->color = BLACK;
    334                     bro->p->color = RED;
    335                     right_rotate(x->p);
    336                     bro = x->p->left;
    337                 }
    338                 if (bro->left->color == BLACK&&bro->right->color == BLACK) { // case 2
    339                     bro->color = RED;
    340                     x = x->p;
    341                 }
    342                 else {
    343                     if (bro->left->color == BLACK) { // case 3
    344                         bro->color = RED;
    345                         bro->right->color = BLACK;
    346                         left_rotate(bro);
    347                         bro = x->p->left;
    348                     }
    349                     bro->left->color = BLACK; // case 4
    350                     bro->color = bro->p->color;
    351                     bro->p->color = BLACK;
    352                     right_rotate(x->p);
    353                     x = rt;
    354                 }
    355             }
    356         }
    357         x->color = BLACK;
    358     }
    359 
    360      RBnode successor(RBnode x) { // 后继节点
    361         if (x->right != nil)
    362             return min_mum(x->right);
    363         RBnode y = x->p;
    364         while (y != nil && y->right == x) {
    365             x = y;
    366             y = y->p;
    367         }
    368         return y;
    369     }
    370 
    371     RBnode predecessor(RBnode x) { // 前继
    372         if (x->left != nil)
    373             return max_mum(x->left);
    374         RBnode y = x->p;
    375         while (y != nil && y->left == x) {
    376             x = y;
    377             y = y->p;
    378         }
    379         return y;
    380     }
    381 
    382 };
    383 
    384 int main()
    385 {
    386 
    387     RBtree<int> tree;
    388     int n;  scanf("%d",&n);
    389     while (n--) {
    390         int op,x; scanf("%d %d",&op,&x);
    391         if (op==1) tree.insert(x);
    392         else if(op==2)  {
    393             node<int>* nd=tree.rfind(x);
    394             tree.remove(nd);
    395         }
    396         else if(op==3) {
    397             node<int>* nd=tree.find(x);
    398             printf("%d
    ",tree.get_rank(nd));
    399         }
    400         else if (op==4)  printf("%d
    ",tree.find_kth(x)->key);
    401         else if (op==5)  printf("%d
    ",tree.low_find(x)->key);
    402         else             printf("%d
    ",tree.upp_find(x)->key);
    403     }
    404     return 0;
    405 }
  • 相关阅读:
    Flutter TextField 文本输入框的基本属性
    Flutter 之网络请求Dio, FormData, 表单网络请求, x-www-form-urlencoded
    操作DataTable数据,修改某列的值
    获取DataTable某一列所有值
    ajax将数据遍历给select的option选项
    Flutter 获取网络数据及渲染列表
    Flutter实现APP版本更新
    Flutter 一些常用库插件
    flutter_screenutil屏幕適配
    前端组件学习
  • 原文地址:https://www.cnblogs.com/xidian-mao/p/11014825.html
Copyright © 2011-2022 走看看