zoukankan      html  css  js  c++  java
  • 【算法导论】学习笔记——第13章 红黑树

    红黑树(red-black tree)是许多平衡搜索树中的一种,因此基本操作(查询、删除、搜索)等在最坏情况下的时间复杂度均为O(lgn)。
    13. 1 红黑树的性质
    红黑树时一棵二叉搜索树,并且在每个结点上增加了一个属性表示颜色:红色或黑色。通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,
    红黑树确保没有一条路径会比其它路径长出2倍。因而是近似于平衡的。
    一棵红黑树是满足下面红黑性质的二叉搜索树:
    1. 每个结点是红色或黑色;
    2. 根结点是黑色的;
    3. 每个叶结点(NIL)是黑色的;
    4. 如果一个结点是红色的,则它的两个子结点都是黑色的;
    5. 对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点。(黑高相等)
    从某个结点x出发到达一个叶结点的任意一条简单路径上的黑色结点个数称为该结点的黑高(black-height)。

    13.1-1
    均不是,若结点为红色不满足性质4;若结点为黑色不满足性质5.

    13.1-2
    仍旧是红黑树,满足性质1-5

    13.1-3
    这个题目描述的不清楚,其实就是把红色结点和黑结点归并到一起组成一个新的结点。因此,
    当黑色父结点的子结点均为黑色时,度为2;
    当黑色父结点仅含一个黑色子结点时,度为3;
    当黑色父结点的两个子结点均为红色时,度为4.
    由于红色结点全部被吸收,即仅余下黑结点。由红黑树性质5可知叶结点深度均相同。

    13.1-4
    这个题目描述的不清楚,其实就是把红色结点和黑结点归并到一起组成一个新的结点。因此,
    当黑色父结点的子结点均为黑色时,度为2;
    当黑色父结点仅含一个黑色子结点时,度为3;
    当黑色父结点的两个子结点均为红色时,度为4.
    由于红色结点全部被吸收,即仅余下黑结点。由红黑树性质5可知叶结点深度均相同。

    13.1-5
    可以先形式化验证, 考虑结点x的黑高为BH(x), 红高为RH(x), 而RH(x)<=BH(x). 结点x到后代叶结
    点的最长路径为BH(x)+RH(x), 最短路径为BH(x). 因此,至多为2倍。再形象地考虑一下路径会是什么样的。
    设x的黑高为h,当x的颜色为黑色,则最长路径的着色为黑-红-黑-...-红-黑-红-黑, 长度为(2h-2),最短路径的着色为黑-黑-...-黑-黑,长度为(h-1), 比值为2 。
    当x的颜色为红色,则最长路径的着色为红-黑-红-黑-...-红-黑-红-黑, 长度为(2h-1),最短路径的着色为红-黑-黑-...-黑-黑,长度为h, 比值趋近于2 。
    因此,综上可知比值最多为2.

    13.1-6
    内部结点最多为2^(2k)-1, 显然为一棵完全数,每层结点颜色为黑-红交替。
    内部结点最少为2^k-1,显然为一棵全黑树。

    13.1-7
    比值最大为2:1, 比值最小为0(全黑树)。

    13.2 旋转
    旋转操作室平衡树中重要的操作之一,红黑树中仅有两种旋转:左旋与右旋。时间复杂度均为O(lgn)。通过左旋与右旋维护红黑树的性质。

     1 void Left_Rotate(Tree_t *t, Node_t *x) {
     2     Node_t *y = x->right;
     3     x->right = y->left;
     4     if (y->left != t->NIL)
     5         y->left->p = x;
     6     y->p = x->p;
     7     if (x->p == t->NIL) {
     8         // x is root
     9         t->root = y;    
    10     } else if (x == x->p->left) {
    11         x->p->left = y;
    12     } else {
    13         x->p->right = y;
    14     }
    15     y->left = x;
    16     x->p = y;
    17 }
    18 
    19 void Right_Rotate(Tree_t *t, Node_t *y) {
    20     Node_t *x = y->left;
    21     y->left = x->right;
    22     if (x->right != t->NIL)
    23         x->right->p = y;
    24     x->p = y->p;
    25     if (y->p == t->NIL) {
    26         // y is root
    27         t->root = x;
    28     } else if (y == y->p->left) {
    29         y->p->left = x;
    30     } else {
    31         y->p->right = x;
    32     }
    33     x->right = y;
    34     y->p = x;
    35 }

    13.2-2


    13.2-3
    a加1,b不变,c减1

    13.2-4


    13.3 插入
    插入操作主要包括RB-INSERT(在适合位置插入元素)与RB-INSERT-FIXUP(维护红黑树性质)。

     1 void RBTree_Insert_Fixup(Tree_t *t, Node_t *z) {
     2     Node_t *y;
     3     
     4     while (z->p->color == RED) {
     5         // means z->p->p->color == BLACK
     6         if (z->p == z->p->p->left) {
     7             y = z->p->p->right;
     8             if (y->color == RED) {
     9                 z->p->color = BLACK;
    10                 y->color = BLACK;
    11                 z->p->p->color = RED;
    12                 z = z->p->p;
    13             } else {
    14                 // y->color is BLACK
    15                 if (z == z->p->right) {
    16                     z = z->p;
    17                     Left_Rotate(t, z);
    18                 }
    19                 z->p->color = BLACK;    // break later
    20                 z->p->p->color = RED;
    21                 Right_Rotate(t, z->p->p);
    22             }
    23         } else {
    24             y = z->p->p->left;
    25             if (y->color == RED) {
    26                 z->p->color = BLACK;
    27                 y->color = BLACK;
    28                 z->p->p->color = RED;
    29                 z = z->p->p;
    30             } else {
    31                 // y->color is BLACK
    32                 if (z == z->p->left) {
    33                     z = z->p;
    34                     Right_Rotate(t, z);
    35                 }
    36                 z->p->color = BLACK;    // break later
    37                 z->p->p->color = RED;
    38                 Left_Rotate(t, z->p->p);
    39             }
    40         }
    41     }
    42     t->root->color = BLACK;
    43 }
    44 
    45 void RBTree_Insert(Tree_t *t, Node_t *z) {
    46     Node_t *y = t->NIL;
    47     Node_t *x = t->root;
    48     while (x != t->NIL) {
    49         y = x;
    50         if (z->key < x->key) {
    51             x = x->left;
    52         } else {
    53             x = x->right;
    54         }
    55     }
    56     z->p = y;
    57     if (y == t->NIL) {
    58         // tree is empty
    59         t->root = z;
    60     } else if (z->key < y->key) {
    61         y->left = z;
    62     } else {
    63         y->right = z;
    64     }
    65     z->left = z->right = t->NIL;
    66     z->color = RED;
    67     RBTree_Insert_Fixup(t, z);
    68 }

    13.3-1
    若将结点z着为黑色,则红黑树的黑高不平衡。破坏性质5,而且难以维护。

    13.3-2


    13.3-4


    13.3-5


    14.4 删除
    与插入过程类似,删除过程主要包括RB-DELETE(基本的删除操作)与RB-DELETE-FIXUP(维护红黑树性质),另外还包括TRANSPLANT操作。

      1 void RBTree_Transplant(Tree_t *t, Node_t *u, Node_t *v) {
      2     if (u->p == t->NIL) {
      3         t->root = v;
      4     } else if (u == u->p->left) {
      5         u->p->left = v;
      6     } else {
      7         u->p->right = v;
      8     }
      9     v->p = u->p;
     10 }
     11 
     12 void RBTree_Delete_Fixup(Tree_t *t, Node_t *x) {
     13     Node_t *w;
     14     
     15     while (x!=t->root && x->color==BLACK) {
     16         if (x == x->p->left) {
     17             w = x->p->right;
     18             if (w->color == RED) {
     19                 w->color = BLACK;
     20                 x->p->color = RED;
     21                 Left_Rotate(t, x->p);
     22                 w = x->p->right;
     23             }
     24             // means w->color == BLACK
     25             if (w->left->color==BLACK && w->right->color==BLACK) {
     26                 w->color = RED;
     27                 x = x->p;    // fetch the black in w & x and pass it to x->p
     28             } else {
     29                 if (w->right->color == BLACK) {
     30                     // means w->left->color == RED
     31                     w->left->color = BLACK;
     32                     w->color = RED;
     33                     Right_Rotate(t, w);
     34                     w = x->p->right;
     35                 }
     36                 // means w->right->color == RED && w->left->color == uncertain
     37                 w->color = x->p->color;
     38                 x->p->color = BLACK;
     39                 w->right->color = BLACK;
     40                 Left_Rotate(t, x->p);
     41                 x = t->root;
     42             }
     43         } else {
     44             w = x->p->left;
     45             if (w->color == RED) {
     46                 w->color = BLACK;
     47                 x->p->color = RED;
     48                 Right_Rotate(t, x->p);
     49                 w = x->p->left;
     50             }
     51             // means w->color == BLACK
     52             if (w->left->color==BLACK && w->right->color==BLACK) {
     53                 w->color = RED;
     54                 x = x->p; // fetch the black in w & x and pass it to x->p
     55             } else {
     56                 if (w->left->color == BLACK) {
     57                     // means x->right->color == RED
     58                     w->right->color = BLACK;
     59                     w->color = RED;
     60                     Left_Rotate(t, w);
     61                     w = x->p->left;
     62                 }
     63                 // means w->left->color == RED && w->right->color = ANY
     64                 w->color = x->p->color;
     65                 x->p->color = BLACK;
     66                 w->left->color = BLACK;
     67                 Right_Rotate(t, x->p);
     68                 x = t->root;
     69             }
     70         }
     71     }
     72     x->color = BLACK;
     73 }
     74 
     75 void RBTree_Delete(Tree_t *t, Node_t *z) {
     76     Node_t *x, *y = z;
     77     bool y_original_color = y->color;
     78     
     79     if (z->left == t->NIL) {
     80         x = z->right;
     81         RBTree_Transplant(t, y, x);
     82     } else if (z->right == t->NIL) {
     83         x = z->left;
     84         RBTree_Transplant(t, y, x);
     85     } else {
     86         y = RBTree_Minimum(t, z->right);
     87         y_original_color = y->color;
     88         x = y->right;
     89         if (y->p == z) {
     90             x->p = y;
     91         } else {
     92             RBTree_Transplant(t, y, x);
     93             y->right = z->right;
     94             y->right->p = y;
     95         }
     96         RBTree_Transplant(t, z, y);
     97         y->left = z->left;
     98         y->left->p = y;
     99         y->color = z->color;
    100     }
    101     
    102     if (y_original_color == BLACK)
    103         RBTree_Delete_Fixup(t, x);    // use x replace y
    104 }

    红黑树的插入和删除操作都需要分类讨论,因此,为了测试自己的红黑树是否正确可以dfs一下测试上述5个性质是否满足。
    一定要注意NIL结点也是黑色的。

    13.4-1


    13.4-2
    证明:
    x.color为RED,而原来y的父结点为RED 。 直接将x的颜色改为BLACK,但这只是最简单的一种情况。

    13.4-3


    13.4-6
    证明:
    情 况1开 始 时, w.color==RED, 因 此w.p.color=BLACK(红 黑 树 性 质), 而w.p==x.p, 因 此 当 情
    况1发生时,x.p.color==BLACK恒成立。

    13.4-7
    不一定一样,个别结点的颜色可能会不一样。可以写个随机数发生器实际测试一下。

  • 相关阅读:
    优先队列总结
    CodeForces 567D One-Dimensional Battle Ships
    CodeForces 567D One-Dimensional Battle Ships
    codeforces 1016B. Segment Occurrences
    codeforces 1016B. Segment Occurrences
    poj3249(求最长路)
    poj3249(求最长路)
    poj 2186
    2017年第八蓝桥杯C/C++ A组国赛 —— 第二题:生命游戏
    Fence Repair POJ
  • 原文地址:https://www.cnblogs.com/bombe1013/p/4296336.html
Copyright © 2011-2022 走看看