• 红黑树


    性质导致了 强约束,也导致了O(lgn)的高度
     
    性质1. 节点是红色或黑色。

    性质2. 根是黑色。

    性质3. 所有叶子都是黑色(叶子是NIL节点)。

    性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

    性质5. 从任一节点(不包括该节点)到其每个叶子的所有简单路径都包含相同数目的黑色节点。
     
    得出的结论
    1 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长
    2 最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点
    3 红色结点的父结点或子节点一定是黑色结点
    4 在五个性质前提下推导出树的高度为o(lgn)的结论,
       即进行插入或删除时,只需关注保持五个性质,而五个性质决定了算法的复杂度为o(lgn)
     
    插入需要注意的点

    1 插入新节点总是红色节点

    2 如果插入节点的父节点是黑色, 能维持性质

    3 如果插入节点的父节点是红色, 破坏了性质. 故需要通过重新着色或旋转, 来维持性质

    插入关键部分

    解决相邻的两个节点为红色的结点,同时维持任意路径黑高度(黑色结点个数)相同

    删除需要需要注意的点

    1 如果删除的是红色节点, 不破坏性质

    2 如果删除的是黑色节点, 那么这个路径上就会少一个黑色节点, 破坏了性质. 故需要通过重新着色或旋转, 来维持性质

    删除关键部分

    如果删除的是左子树黑色结点,维持的最终目的是左右黑高度相同,即维持右子树黑高度的同时,增加左子树的黑高度

    代码主要根据上图实现 

      1 #include <iostream>
      2 #include <crtdbg.h>
      3 #include <string>
      4 using namespace std;
      5 /*红黑树*/
      6 /*实现中假设关键元素互不相同*/
      7 typedef int DataType;
      8 
      9 class BST
     10 {
     11 private:
     12     enum {BLACK = 0, RED = 1};
     13     /*结点的数据结构*/
     14     struct node
     15     {
     16         DataType data;
     17         bool color;
     18         node *left;
     19         node *right;
     20         node *parent;
     21 
     22         node()
     23         {
     24             color = RED;
     25             left = NULL;
     26             right = NULL;
     27             parent = NULL;
     28             data = 0;
     29         }
     30         node *Grandfather()
     31         {
     32             if (parent == NULL)
     33             {
     34                 return NULL;
     35             }
     36             return parent->parent;
     37         }
     38         node *Uncle()
     39         {
     40             if(Grandfather() == NULL)
     41                 return NULL;
     42             if (parent == Grandfather()->left)
     43             {
     44                 return Grandfather()->right;
     45             }
     46             else
     47             {
     48                 return Grandfather()->left;
     49             }
     50         }
     51         node *Sibling()
     52         {
     53             if (parent->left == this)
     54             {
     55                 return parent->right;
     56             }
     57             else
     58             {
     59                 return parent->left;
     60             }
     61         }
     62     };
     63     void Left_rotate(node *p )
     64     {
     65         //把y的左子树连接到p的右子树下面,并更新父节点
     66         node *y = p->right;
     67         p->right = y->left;
     68         if (y->left != NIL)
     69         {
     70             y->left->parent = p;
     71         }
     72         //更新y的父节点
     73         y->parent = p->parent;
     74         if (p->parent == NIL) //判断根结点
     75         {
     76             root = y;
     77         }
     78         //更新原x父节点的子节点
     79         else if (p == p->parent->left)
     80         {
     81             p->parent->left = y;
     82         }
     83         else
     84         {
     85             p->parent->right = y;
     86         }
     87         //更新x 与 y 的关系
     88         y->left = p;
     89         p->parent = y;
     90     }
     91     void Right_rotate(node *p)
     92     {
     93         node *y = p->left;
     94         p->left = y->right;
     95         if (y->right != NIL)
     96         {
     97             y->right->parent = p;
     98         }
     99         y->parent = p->parent;
    100         if (p->parent == NIL) //判断根结点
    101         {
    102             root = y;
    103         }
    104         else if (p == p->parent->left)
    105         {
    106             p->parent->left = y;
    107         }
    108         else
    109         {
    110            p->parent->right = y;
    111         }
    112         y->right = p;
    113         p->parent = y;
    114     }
    115     string OutputColor(bool color)
    116     {
    117         return color ? "RED":"BLACK";
    118     }
    119     /*纠正因插入而破坏的性质*/
    120     void Insert_Fixup(node *p)
    121     {
    122         /*由于p结点为红色(新插入默认赋值为红色),
    123           判断p的父节点是否为红色,如果为红色则破坏了红黑树的性质,需要维护*/
    124         while(p->parent->color == RED)
    125         {
    126             if (p->parent == p->Grandfather()->left) 
    127             {
    128                 node *y = p->Grandfather()->right;
    129                 if (y->color == RED)  /*case 3*/
    130                 {
    131                     p->parent->color = BLACK;
    132                     y->color = BLACK;
    133                     p->Grandfather()->color = RED;
    134                     p = p->Grandfather();/*p结点向上移*/
    135                 }
    136                 else if (p == p->parent->right) /*case 2*/
    137                 {
    138                     p = p->parent;/*p结点向上移*/
    139                     Left_rotate(p);
    140                 }
    141                 else
    142                 {
    143                     p->parent->color = BLACK; /*case 3*/
    144                     p->Grandfather()->color = RED;
    145                     Right_rotate(p->Grandfather());/*注意是祖父结点*/
    146                 }
    147             }
    148             else
    149             {
    150                 node *y = p->Grandfather()->left;
    151                 if (y->color == RED)  /*case 3*/
    152                 {
    153                     p->parent->color = BLACK;
    154                     y->color = BLACK;
    155                     p->Grandfather()->color = RED;
    156                     p = p->Grandfather();
    157                 }
    158                 else if (p == p->parent->left) /*case 2*/
    159                 {
    160                     p = p->parent;
    161                     Right_rotate(p);
    162                 }
    163                 else
    164                 {
    165                     p->parent->color = BLACK; /*case 3*/
    166                     p->Grandfather()->color = RED;
    167                     Left_rotate(p->Grandfather());
    168                 }
    169             }
    170         }
    171         root->color = BLACK;/*确保插入根结点时,满足红黑树的性质*/
    172     }
    173     /*纠正因删除而破坏的性质*/
    174     void Delete_Fixup(node *p)
    175     {
    176         /*判断p结点是否为黑色
    177          如果是红色不破坏红黑树性质
    178          原因1.删除红色树黑高度不变2.不存在两个相邻红色结点
    179          3. 如果y是红色的,就不可能是根,即根仍然是黑色的
    180          为保证性质任何路径上黑结点个数相同,假设p结点为多重颜色(双黑或红黑)*/
    181         while (p != root && p->color == BLACK)
    182         {
    183             if(p == p->parent->left)
    184             {
    185                 node *pSibling = p->parent->right;
    186                 if (pSibling->color == RED)/*case1*/
    187                 {
    188                     pSibling->color = BLACK;
    189                     Left_rotate(p->parent);
    190                     pSibling = p->parent->right;
    191                 }
    192                 else if (pSibling->left->color == BLACK && pSibling->right->color == BLACK)/*case2*/
    193                 {
    194                     pSibling->color = RED;
    195                     p = p->parent;
    196                 }                
    197                 else
    198                 {
    199                     if (pSibling->right->color == BLACK)/*case3*/
    200                     {
    201                         pSibling->left->color = BLACK;
    202                         pSibling->color = RED;
    203                         Right_rotate(pSibling);
    204                         pSibling = p->parent->right;
    205                     }
    206                     pSibling->color = p->parent->color;/*case4*/
    207                     p->parent->color = BLACK;
    208                     pSibling->right->color = BLACK;
    209                     Left_rotate(p->parent);
    210                     p = root;
    211                 }
    212             }
    213             else
    214             {
    215                 node *pSibling = p->parent->left;
    216                 if (pSibling->color == RED)/*case1*/
    217                 {
    218                     pSibling->color = BLACK;
    219                     Left_rotate(p->parent);
    220                     pSibling = p->parent->left;
    221                 }
    222                 else if (pSibling->left->color == BLACK && pSibling->right->color == BLACK)/*case2*/
    223                 {
    224                     pSibling->color = RED;
    225                     p = p->parent;
    226                 }                
    227                 else
    228                 {
    229                     if (pSibling->left->color == BLACK)/*case3*/
    230                     {
    231                         pSibling->right->color = BLACK;
    232                         pSibling->color = RED;
    233                         Left_rotate(pSibling);
    234                         pSibling = p->parent->left;
    235                     }
    236                     pSibling->color = p->parent->color;/*case4*/
    237                     p->parent->color = BLACK;
    238                     pSibling->right->color = BLACK;
    239                     Right_rotate(p->parent);
    240                     p = root;
    241                 }
    242             }
    243         }
    244         p->color = BLACK;
    245     }
    246     /*中序遍历*/
    247     void InOrderTree(node *p)
    248     {
    249         if (p == NULL || p == NIL)
    250         {
    251             return;
    252         }
    253         InOrderTree(p->left);
    254         cout << p->data << "	" << OutputColor(p->color) << endl;
    255         InOrderTree(p->right);
    256     }
    257     /*获取结点的后继*/
    258     node *TreeAfter(node *p)
    259     {
    260         if (p->right != NIL)
    261         {
    262             node *pTemp = p->right;
    263             while(pTemp != NIL)
    264             {
    265                 p = pTemp;
    266                 pTemp = p->left;
    267             }
    268         }
    269         return p;
    270     }
    271 private:
    272     node *root;
    273     node *NIL;
    274 public:
    275     BST()
    276     {
    277         NIL = new node();
    278         NIL->color = BLACK;
    279         root = NULL;
    280     }
    281     ~BST()
    282     {
    283         if (root != NULL)
    284         {
    285             Destory(root);
    286             root = NULL;
    287         }
    288         delete NIL;
    289         NIL = NULL;
    290     }
    291     void Destory(node *p)
    292     {
    293         if (p == NULL || p == NIL)
    294             return;
    295         Destory(p->left);
    296         Destory(p->right);
    297         delete p;
    298     }
    299     void Insert(DataType data)
    300     {
    301         node *p = root;
    302         node *pTemp = NIL;
    303         while( p != NIL && p != NULL)
    304         {
    305             pTemp = p;
    306             if (data < p->data)
    307             {
    308                 p = p->left;
    309             }
    310             else
    311             {
    312                 p = p->right;
    313             }
    314         }
    315         node *pNew = new node();
    316         pNew->parent = pTemp;
    317         pNew->data = data;
    318         if (pTemp == NIL)
    319         {
    320             root = pNew;
    321         }
    322         else
    323         {
    324             if (pNew->data < pTemp->data)
    325             {
    326                 pTemp->left = pNew;
    327             }
    328             else
    329             {
    330                 pTemp->right = pNew;
    331             }
    332         }
    333         pNew->left = NIL;
    334         pNew->right = NIL;
    335         Insert_Fixup(pNew);
    336     }
    337     /*非递归版本*/
    338     node* Find(DataType key)
    339     {
    340         node *p = root;
    341         while(p != NULL && p->data != key)
    342         {
    343             if (key < p->data)
    344             {
    345                 p = p->left;
    346             }
    347             else
    348             {
    349                 p = p->right;
    350             }
    351         }
    352         return p;
    353     }
    354     void Delete(DataType data)
    355     {
    356         /*获取data的指针*/
    357         node *p = Find(data);
    358         node *pDelete= NIL;
    359         node *pNode = NIL;/*要删除节点的子节点*/
    360         if (p->left == NIL || p->right == NIL)
    361         {
    362             pDelete = p;
    363         }
    364         else
    365         {
    366             pDelete = TreeAfter(p);
    367         }
    368         /*获取子结点*/
    369         if(pDelete->left != NIL)
    370         {
    371             pNode = pDelete->left;
    372         }
    373         else
    374         {
    375             pNode = pDelete->right;
    376         }
    377         /*更新父结点*/
    378         pNode->parent = pDelete->parent;
    379         /*更新子结点*/
    380         if (pDelete->parent == NIL)
    381         {
    382             root = pNode;
    383         }
    384         else if(pDelete->parent->left == pDelete)
    385         {
    386             pDelete->parent->left = pNode;
    387         }
    388         else
    389         {
    390             pDelete->parent->right = pNode;
    391         }
    392         if (pDelete != p)
    393         {
    394             p->data = pDelete->data;
    395         }
    396         /*如果要删除的结点pDelete是红色的,
    397         不影响黑高度,即不会破坏红黑树的性质*/
    398         if (pDelete->color == BLACK)
    399         {
    400             Delete_Fixup(pNode);
    401         }
    402         delete pDelete;
    403         pDelete = NULL;
    404     }
    405     void InOrder()
    406     {
    407         if (root == NULL)
    408         {
    409             return;
    410         }
    411         InOrderTree(root);
    412         cout << endl;
    413     }
    414 };
    415 
    416 void main()
    417 {
    418     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    419 
    420      BST bst;
    421      
    422      bst.Insert(11);
    423      bst.Insert(2);
    424      bst.Insert(14);
    425      bst.Insert(15);
    426      bst.Insert(1);
    427      bst.Insert(7);
    428      bst.Insert(5);
    429      bst.Insert(8);
    430      bst.Insert(4);
    431 
    432      bst.InOrder();
    433 
    434      //bst.Delete(4);
    435      //bst.Delete(14);
    436      bst.Delete(7);
    437      bst.InOrder();
    438 
    439     system("pause");
    440 }

     (转载请注明作者和出处 :)  Seven++ http://www.cnblogs.com/sevenPP/  )

  • 相关阅读:
    100个经典的动态规划方程
    poj 2105 IP Address
    codeforces 299 A. Ksusha and Array
    codeforces 305 C. Ivan and Powers of Two
    性能测试实战 | 修改 JMeter 源码,定制化聚合压测报告
    Pytest 测试框架训练营,测试大咖带你搞定自动化+接口测试实战 | 限时免费报名
    MTSC 测试开开发大会(深圳站),报名立减 100 元!
    测试人面试 BAT 大厂之前,需要做好哪些准备?
    iOS 自动化测试踩坑(二):Appium 架构原理、环境命令、定位方式
    【北京】美团打车招聘职位
  • 原文地址:https://www.cnblogs.com/sevenPP/p/3733450.html
Copyright © 2020-2023  润新知