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

    平衡树:
    1. AVL 树
    2. 2-3 树
    3. 2-3-4 树
    4. 红黑树
    5. B-树
     
    红黑树的性质:
    1.每个结点要么是黑色或者红色。
    2.根结点和叶节点(nil)是黑色。
    3.如果一个结点是红色的,则它的父结点和两个子结点都是黑色的。
    4.对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点,称为黑高。bh(x)
     
    推论:
    1.一棵有n个结点的红黑树高度至多为2lg(n + 1)。
     
    • 插入操作
      关键:使用recolor 和 rotation 操作维持RBT的红黑属性。
      1. case1: x的叔结点y是红色的。
      2. case2: x的叔结点y是黑色的且x是一个右孩子。
      3. case3: x的叔结点y是黑色的且x是一个左孩子。
      一次插入操作时间复杂度:O(lgn)
    RB-Insert(T, z):
        y = T.nil.                            // 二叉搜索树的插入操作
        x = T.root
        while x != T.nil:
            y = x
            if z.key < x.key:
                x = x.left
            else:
                x = x.right
        z.p = y
        if y == T.nil:
            T.root = z
        else if z.key < y.key:
            y.left = z
        else:
            y.right = z
        z.left = T.nil
        z.right = T.nil
        z.color = RED
        RB-INSERT-FIXUP(T, z)
     
    RB-INSERT-FIXUP(T, z):
        while z != T.root and z.p.color == RED:
            if z.p == z.p.p.left:
                y = z.p.p.right
                if y.color = RED:            // case1: 将 z 祖父结点的Black属性下移给其子节点
                    z.p.color = BLACK        // 因为 z.p 和 y 都是Red属性,所以对称转移不会改变RBT的属性
                    y.color = BLACK
                    z.p.p.color = RED
                    z = z.p.p
                else if z == z.p.right:      // case2: z 是右子结点,对x父结点左旋将 z 和 z.p 放在一条直线上
                        z = z.p
                        LEFT_ROTATION(T, z)
                    z.p.color = BLACK        // case3: 可能由case2转移得到,先重新着色,再对 z 祖父结点右旋将 z 的父结点作为新子树的根结点 
                    z.p.p.color = RED
                    RIGHT_ROTATION(T, z.p.p)
            else:                           // 对称如果 z 父结点是右子树结点,有3种case
                // same as above with “right” and “left” exchanged
        T.root.color = BLACK
    • 删除操作
      恢复红黑树属性。
      1. case1: x 的兄弟结点 w 是红色的。
      2. case2: x 的兄弟结点 w 是黑色的,而且 w 的两个子结点都是黑色的。
      3. case3: x 的兄弟结点 w 是黑色的,w 的左子结点是红色的,右子结点是黑色的。
      4. case4: x 的兄弟结点 w 是黑色的,w 的右子结点是红色的。
      一次删除操作时间复杂度:O(lgn)
    RB-TRANSPLANT(T, u, v):       // 用子树 v 代替 u
        if u.p == T.nil:
            T.root = v
        else if u == u.p.left:
            u.p.left = v
        else:
            u.p.right = v
        v.p = u.p
     
    RB- DELETE(T, z):
        y = z
        y_original_color = y.color
        if z.left = T.nil:                // case1: 被删除结点只有右子结点
            x = z.right
            RB-TRANSPLANT(T, y, x)        // 将 x 移到 y 的原始位置
        else if z.right = T.nil:          // case2: 被删除结点只有左子结点
            x = z.left
            RB-TRANSPLANT(T, y, x) 
        else:                            // case3: 被删除结点有左右子结点
            y = TREE-MINIMUM(z.right)    // 找到后继结点 y
            y_original_color = y.color
            x = y.right
            if y.p == z:                 // 其他情况:x.p = y.p    
                x.p = y
            else:
                RB-TRANSPLANT(T, y, x)   // 将 x 移到 y 的原始位置
                y.right = z.right        // 原 z 的左右子结点要转移成 y 的左右子结点
                y.right.p = y
            RB-TRANSPLANT(T, z, y)       // 将 y 移到 z 的原始位置
            y.left = z.left              // 原 z 的左右子结点要转移成 y 的左右子结点
            y.left.p = y
            y.color = z
        if y-original-color == BLACK:    // 如果删除/移动的是红色结点不影响RBT树的红黑属性
            RB-DELETE-FIXUP(T, x)        // 否则要维护树的红黑属性
     
     
    /*
    如果 y.color是黑色,则上述删除操作可能造成3个问题:
    1.如果 y 是原来的根结点,而 y 的一个红色孩子成为新的根结点,违反性质2.
    2.如果 x 和 x.p (原 y.p)都是红色,违反性质3.
    3.在树中移动 y 结点将导致先前包含 y (之后不包含)的任何简单路径上黑结点个数少1,因此 y 的任何子线不满足性质4.
    改正这一问题的办法是:将现在占有 y 原来位置的结点 x 视为还有一重额外的黑色。即:如果将任意包含结点 x 的简单路径上黑结点个数加1,则在这种假设下,性质4成立。当黑结点 y 删除或移动时,将其黑色属性“下推”给 x。现在的 x 是双重黑色或者红黑色,分别给包含 x 的简单路径上黑结点数贡献2或1。x 的color属性仍然是RED(如果 x 是红黑色的)或者BLACK(如果 x 是双重黑色的)。换而言之,结点额外的黑色是针对 x 结点的,而不是反映在它的color属性上。
    */
     
    RB-DELETE-FIXUP(T, x):
        while x != T.root and x.color == BLACK:
            if x == x.p.left:                   
                w = x.p.right
                if w.color == RED:           // case1: 将 x 父结点左旋,转移到case2
                    w.color = BLACK
                    x.p.color = RED
                    LEFT-ROTATION(T, x.p)
                    w = x.p.right
                if w.left.color == BLACK and w.right.color == BLACK:  // case2
                    w.color = RED
                    x = x.p
                else if w.right.color == BLACK:       // case3
                        w.left.color = BLACK
                        w.color = RED
                        RIHGT-ROTATION(T, w)
                        w = x.p.right
                    w.color = x.p.color              // case4
                    x.p.color = BLACK
                    w.right.color = BLACK
                    LEFT-ROTATION(T, x.p)
                    x = T.root
            else:
                // same as above with “right” and “left” exchanged
        x.color = BLACK           
    • 应用
     (参看《算法导论》)
  • 相关阅读:
    FZU 2104 Floor problem (水题)
    POJ 1797 Heavy Transportation (最短路变形)
    ZOJ 3708 Density of Power Network (水题)
    POJ 2488 A Knight's Journey (DFS)
    HDU 1198 Farm Irrigation (并查集)
    HDU 1052 Tian Ji -- The Horse Racing (贪心)
    HDU 1598 find the most comfortable road (并查集||最短路)
    poj 2533 Longest Ordered Subsequence(最长上升子序列)
    hdu 2025 查找最大元素 (水)
    hdu 5142 NPY and FFT(水)
  • 原文地址:https://www.cnblogs.com/tristatl/p/15120658.html
Copyright © 2011-2022 走看看