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

    做过简单的测试,应该没什么大问题。想想算法导论这部分看了很久,又撸过AVL写起来还是有点小迷糊,也在迷糊中学了点东西。总之继续吧

    Rb_tree.h

      1 #pragma once
      2 
      3 #include <iostream>
      4 
      5 enum color{RED,BLACK};
      6 
      7 template<class T>
      8 struct node {
      9     node* p;
     10     node *left, *right;
     11     T key;
     12     color c;
     13     int siz;
     14     
     15     node(){}
     16     node(T key):p(0),left(0),right(0), key(key){}
     17 };
     18 
     19 template<class T>
     20 class RbTree {
     21 private:
     22     //typedef struct node node;
     23     node<T>* Root;
     24     node<T>* Nil;//代表本树的nullptr,主要方便去除后的平衡调整
     25 public:
     26     RbTree() :Nil(new node<T>()), Root(0) {
     27         Root = Nil;
     28         Nil->c = BLACK;//叶节点
     29         Nil->siz = 0;
     30     }
     31     ~RbTree() {
     32         destroy(Root); 
     33         delete Nil;
     34     }
     35     
     36     void preorder() { _preorder(Root); }
     37     void insert(T key) {
     38         node<T>* xixi = new node<T>(key);
     39         if (xixi == 0) {//申请内存失败
     40             std::cerr << "new node fail!" << endl;
     41             return;
     42         }
     43 
     44         _insert(xixi);
     45     }
     46     void remove(T key) {
     47         _remove(key);
     48     }
     49     //找到第i顺序统计量对应的关键字
     50     T os_select(int i) { return (select(Root, i))->key; }
     51     //确定关键字key的顺序统计量
     52     int os_rank(T key) { return rank(find(key)); }
     53 
     54 private:
     55     void _preorder(node<T>* u);
     56     void destroy(node<T>* u);
     57     void _insert(node<T>* u);
     58     void _remove(T key);
     59     void leftrotate(node<T>* u);
     60     void rightrotate(node<T>* u);
     61     void transplant(node<T>* u, node<T>* v);
     62     void rb_delete_fixup(node<T>* x);
     63     void rb_insert_fixup(node<T>* x);
     64     node<T>* minimum(node<T>* u);
     65     node<T>* find(T key);
     66     void size_fixup(node<T>* x,int dealta_siz);//添加第二个参数可以给delete和Insert一起用
     67     //找到顺序统计量i的节点
     68     node<T>* select(node<T>* root, int i);
     69     //确定u的顺序统计量
     70     int rank(node<T>* u);
     71 };
     72 template<class T>
     73 node<T>* RbTree<T>::select(node<T>* root, int i) {
     74     if (root->left->siz + 1 == i)return root;
     75     //else
     76     if (i - 1 < root->left->siz)return select(root->left, i);
     77     else return select(root->right, i - 1 - root->left->siz);
     78 }
     79 
     80 template<class T>
     81 int RbTree<T>::rank(node<T>* u) {
     82     int r = u->left->siz + 1;
     83     while (u != Root) {
     84         if (u == u->p->right)
     85             r += u->p->left->siz + 1;
     86         u = u->p;
     87     }
     88     return r;
     89 }
     90 
     91 template<class T>
     92 void RbTree<T>::size_fixup(node<T>* x, int delta_siz) {
     93     while (x->p != Nil) {
     94         x = x->p;
     95         x->siz += delta_siz;
     96     }
     97 }
     98 
     99 template<class T>
    100 void RbTree<T>::rb_delete_fixup(node<T>* x) {
    101     size_fixup(x, -1);//沿简单路径向上修改siz属性
    102 
    103     while (x != Root&&x->c == BLACK) {
    104         node<T>* w;
    105         if (x == x->p->left) {
    106             w = x->p->right;
    107             if (w->c == RED) {//case 1
    108                 w->c = BLACK;
    109                 x->p->c = RED;
    110                 leftrotate(x->p);
    111                 w = x->p->right;//重置
    112             }
    113             //case 2 3 4,对应w节点颜色为黑色
    114                 if (w->left->c == BLACK&&w->right->c == BLACK) {
    115                     w->c = RED;
    116                     x = x->p;//上移
    117                 }
    118                 else {
    119                     if (w->right->c == BLACK) {
    120                         w->c = RED;
    121                         w->left->c = BLACK;
    122                         rightrotate(w);
    123                         w = x->p->right;
    124                     }
    125                     w->c = x->p->c;
    126                     x->p->c = BLACK;
    127                     w->right->c = BLACK;
    128                     leftrotate(x->p);
    129                     x = Root;//退出循环
    130                 }        
    131         }
    132         else {//
    133             w = x->p->left;
    134             if (w->c == RED) {
    135                 x->p->c = RED;
    136                 w->c = BLACK;
    137                 rightrotate(x->p);
    138                 w = x->p->left;
    139             }
    140             if (w->right->c == BLACK&&w->left->c == BLACK) {
    141                 w->c = RED;
    142                 x = x->p;
    143             }
    144             else {
    145                 if (w->left->c == BLACK) {
    146                     w->c = RED;
    147                     w->right->c = BLACK;
    148                     leftrotate(w);
    149                     w = x->p->left;
    150                 }//case 4
    151                 w->c = x->p->c;
    152                 x->p->c = BLACK;
    153                 w->left->c = BLACK;
    154                 rightrotate(x->p);
    155                 x = Root;
    156             }
    157         }
    158     }
    159 
    160     x->c = BLACK;
    161 }
    162 
    163 template<class T>
    164 node<T>* RbTree<T>::minimum(node<T>* u) {
    165     if (u == Nil)return Nil;
    166     while (u->left != Nil)
    167         u = u->left;
    168     return u;
    169 }
    170 
    171 template<class T>
    172 node<T>* RbTree<T>::find(T key) {
    173     node<T>* u = Root;
    174     while (u != Nil&&u->key != key) {
    175         if (u->key > key)
    176             u = u->left;
    177         else u = u->right;
    178     }
    179     if (u == Nil) 
    180         std::cout << "找不到key值为" << key << "的节点" << std::endl;
    181     return u;
    182 }
    183 
    184 template<class T>
    185 void RbTree<T>::_remove(T key) {
    186     node<T>* z = find(key);
    187     if (z == Nil)return;//找不到要删除的节点
    188     node<T>* y = z;
    189     node<T>* x;
    190     color original_c = y->c;
    191     if (z->left == Nil) {
    192         x = z->right;
    193         transplant(z, z->right);
    194     }
    195     else if (z->right == Nil) {
    196         x = z->left;
    197         transplant(z, z->left);
    198     }
    199     else {
    200         y = minimum(z->right);//后继点,用于代替z
    201         original_c = y->c;
    202         x = y->right;
    203         if (y == z->right)
    204             x->p = y;
    205         else {
    206             y->right = z->right;
    207             y->right->p = y;
    208             transplant(y, x);//顺序很重要,x可能是空结点
    209         }
    210 
    211         transplant(z, y);
    212         y->left = z->left;
    213         y->left->p = y;
    214         y->c = z->c;
    215     }
    216     if (original_c == BLACK)
    217         rb_delete_fixup(x);
    218 
    219     delete z;
    220 }
    221 
    222 template<class T>
    223 void RbTree<T>::rb_insert_fixup(node<T>* x) {
    224     size_fixup(x, 1);
    225 
    226     while (x->p->c == RED) {//此条件可保证x->p->必定存在
    227         if (x->p == x->p->p->left) {//x的父节点在x的爷爷的左侧
    228             node<T>* y = x->p->p->right;//叔节点哦
    229             if (y->c == RED) {//case 1
    230                 y->c = BLACK;
    231                 x->p->c = BLACK;
    232                 x->p->p->c = RED;
    233                 x = x->p->p;//节点上移
    234             }
    235             else{
    236                 if (x == x->p->right){//case 2
    237                     x = x->p;
    238                     leftrotate(x);
    239                 }
    240                 x->p->c = BLACK;
    241                 x->p->p->c = RED;
    242                 rightrotate(x->p->p);
    243             }
    244         }
    245         else {//x->p==x->p->p->right
    246             node<T>* y = x->p->p->left;
    247             if (y->c == RED) {//case 1
    248                 y->c = BLACK;
    249                 x->p->c = BLACK;
    250                 x->p->p->c = RED;
    251                 x = x->p->p;
    252             }
    253             else {//叔节点y为黑色 分两种情况,其中case2可转化为case3
    254                 if (x == x->p->left) {//case 2
    255                     x = x->p;
    256                     rightrotate(x);
    257                 }//case 3
    258                 x->p->c = BLACK;
    259                 x->p->p->c = RED;
    260                 leftrotate(x->p->p);
    261             }
    262         }
    263 //while循环
    264     }
    265     Root->c = BLACK;
    266 }
    267 
    268 template<class T>
    269 void RbTree<T>::_insert(node<T>* u) {
    270     node<T>* y = Nil;
    271     node<T>* x = Root;
    272     while (x != Nil) {
    273         y = x;
    274         if (u->key < x->key)
    275             x = x->left;
    276         else x = x->right;
    277     }
    278 
    279     u->p = y;
    280     if (y == Nil)Root = u;//原树为空
    281     else if (u->key < y->key)
    282         y->left = u;
    283     else
    284         y->right = u;
    285 
    286     u->left = Nil;
    287     u->right = Nil;
    288     u->c = RED;
    289     u->siz = 1;
    290 
    291     rb_insert_fixup(u);
    292 }
    293 
    294 template<class T>
    295 void RbTree<T>::transplant(node<T>* u, node<T>* v) {//建立u->p和v的联系
    296     if (u->p == Nil)
    297         Root = v;
    298     else if (u == u->p->left)
    299         u->p->left = v;
    300     else 
    301         u->p->right = v;
    302 
    303     v->p = u->p;//对v是Nil的情况不做特殊讨论
    304 
    305 }
    306 
    307 template<class T>
    308 void RbTree<T>::rightrotate(node<T>* u) {//调用该函数默认左孩子不为Nil
    309     node<T>* lc = u->left;
    310     lc->p = u->p;
    311     if (u->p == Nil)
    312         Root = lc;
    313     else if (u == u->p->left)
    314         u->p->left = lc;
    315     else
    316         u->p->right = lc;
    317 
    318     u->left = lc->right;
    319     if (lc->right != Nil)u->left->p = u;
    320 
    321     lc->right = u;
    322     u->p = lc;
    323     //change the size
    324     u->siz = u->left->siz + u->right->siz + 1;
    325     lc->siz = lc->left->siz + lc->right->siz + 1;
    326 }
    327 
    328 template<class T>
    329 void RbTree<T>::leftrotate(node<T>* u) {//调用该函数默认右孩子不为Nil
    330     node<T>* rc = u->right;
    331     rc->p = u->p;
    332     if (u->p == Nil)
    333         Root = rc;
    334     else if (u == u->p->left)
    335         u->p->left = rc;
    336     else
    337         u->p->right = rc;
    338 
    339     u->right = rc->left;
    340     if (rc->left != Nil)u->right->p = u;
    341 
    342     rc->left = u;
    343     u->p = rc;
    344     //change the size
    345     u->siz = u->left->siz + u->right->siz + 1;
    346     rc->siz = rc->left->siz + rc->right->siz + 1;
    347 }
    348 
    349 template<class T>
    350 void RbTree<T>::destroy(node<T>* u) {
    351     if (u == Nil)return;
    352     destroy(u->left);
    353     destroy(u->right);
    354 
    355     delete u;
    356 }
    357 
    358 template<class T>
    359 void RbTree<T>::_preorder(node<T>* u) {
    360     if (u == Nil)return;
    361 
    362     if (u->p == Nil)std::cout << u->key << "是树根哦" << std::endl;
    363     else if (u == u->p->left)std::cout << u->key << "" << u->p->key << "的左孩子" << std::endl;
    364     else std::cout << u->key << "" << u->p->key << "的右孩子" << std::endl;
    365     std::cout << "颜色为" << (u->c == RED ? "红色" : "黑色") << std::endl;
    366     std::cout << "大小为" << u->siz << endl;
    367     _preorder(u->left);
    368     _preorder(u->right);
    369 }

    test.cpp

     1 #include <iostream>
     2 #include "RB_tree.h"
     3 
     4 using namespace std;
     5 
     6 int main(void) {
     7     RbTree<int> xixi;
     8     xixi.insert(11);
     9     xixi.insert(2);
    10     //xixi.insert(1);
    11     xixi.insert(1);
    12     xixi.insert(7);
    13     xixi.insert(5);
    14     xixi.insert(8);
    15     xixi.insert(4);
    16     xixi.insert(14);
    17     xixi.insert(15);
    18     //xixi.remove(14);
    19     //xixi.remove(11);
    20     //xixi.remove(2);
    21 
    22     xixi.preorder();
    23     int i;
    24 
    25     //cout << "请输入一个合法顺序统计量" << endl;
    26     /*while (cin >> i) {
    27         if (i <= 0)break;
    28         cout << "关键字为" << xixi.os_select(i) << endl;
    29         cout << "请输入一个合法顺序统计量" << endl;
    30     }*/
    31 
    32     cout << "请输入一个合法关键字" << endl;
    33     while (cin >> i) {
    34         cout << "该关键字顺序统计量为" << xixi.os_rank(i) << endl;
    35         cout << "请输入一个合法关键字" << endl;
    36     }
    37 
    38     return 0;
    39 }
  • 相关阅读:
    [Notes] 如何使用abode audition录歌
    [Tips] matlab save load
    [Tips] matlab csv格式文件读写
    [Tips] 随机数 随机序列 随机排列生成
    [Tips] csv 读写
    [record] 初入android
    HTML中表格table边框border(1px还嫌粗)的解决方案:
    CSS颜色代码大全
    ie9下面的console的bug
    js 性能优化 篇一
  • 原文地址:https://www.cnblogs.com/schsb/p/8669290.html
Copyright © 2011-2022 走看看