红黑树

红黑树

红黑树的介绍

红黑树是一种特殊的二叉搜索树, 每个节点多出了一个颜色属性,并满足一下 5 条性质

  1. 每个节点或者是黑色,或者是红色
  2. 根节点是黑色的
  3. 空的叶子节点是黑色的
  4. 红色节点的孩子是黑色的
  5. 每个节点到叶子的路径包含相同的黑色节点

红黑树的性质

引理

n 个内部节点的红黑树最大高度为

证明

先证以 x 为根的子树最少有 个内部节点.

  1. 当 x 为空的叶子节点时, 以 x 为根的子树有 个内部节点, 满足.
  2. 当 x 有两个内部孩子节点时, 孩子节点的黑色高度(black-height)为 bh(x) (/* 当 x 为红色节点/) 或者为 bh(x) -1 (/ 当 x 为黑色节点 */)
  3. 所以 x 的节点数目
  4. 又 , 所以
  5. 所以

旋转

左旋

  1. x 右孩子 y 的左孩子成为 x 的右孩子
  2. x 成为 y 的左孩子
  3. y 取代 x 的位置

右旋

  1. x 左孩子 y 的右孩子成为 x 的左孩子
  2. x 成为 y 的右孩子
  3. y 取代 x 的位置

插入

  1. 根据 key 值的大小插入新的节点 z, 颜色为红色
  2. 若插入的是根节点, 只需要把根设为黑色
  3. 若插入节点 z 的 parent 是红色的
    i. z 的 uncle 是红色的, 将 parent 和 uncle 设为黑色, grandparent 设为红色, 将 grandparent 当成插入节点, 重新判断
    ii. z 的 uncle 是黑色的(tip. T.nil 也是黑色的), 将 z 到 uncle 的路径调为人形, parent 设为黑色 grandparent 设为红色, 将 grandparent 向 uncle 方向旋转
template 
void RBTree::leftRoate(RBNode* x)
{
    RBNode* y = x->right;
    x->right     = y->left;
    if (x->right) x->right->parent = x;
    y->parent = x->parent;
    if (!y->parent)
        root = y;
    else if (y->parent->left == x)
        y->parent->left = y;
    else
        y->parent->right = y;
    y->left   = x;
    x->parent = y;
}

template 
void RBTree::rightRoate(RBNode* x)
{
    RBNode* y = x->left;
    x->right     = y->left;
    if (y->left) y->left->parent = y;
    y->parent = x->parent;
    if (!y->parent)
        root = y;
    else if (y->parent->left == x)
        y->parent->left = y;
    else
        y->parent->right = y;
    y->right  = x;
    x->parent = y;
}

template 
void RBTree::insert(T key)
{
    RBNode* z  = new RBNode(RED, key, nullptr, nullptr, nullptr);
    RBNode* px = root;
    RBNode* py = nullptr;
    while (root)
    {
        py = px;
        if (key < px->key)
            px = px->left;
        else
            px = px->right;
    }
    z->parent = py;
    if (!py)
        root = z;
    else if (z->key < py->key)
        py->left = z;
    else
        py->right = z;
    insertFix(z);
}

template 
void RBTree::insertFix(RBNode* z)
{
    while (z->parent && z->parent->color == RED)
    {
        if (z->parent == z->parent->parent->left)
        {
            RBNode* uncle = z->parent->parent->right;
            if (uncle && uncle->color == RED)
            {
                uncle->color             = BLACK;
                z->parent->color         = BLACK;
                z->parent->parent->color = RED;
                z                        = z->parent->parent;
            }
            else if (z == z->parent->right)
            {
                z = z->parent;
                leftRoate(z);
            }
            z->parent->color         = BLACK;
            z->parent->parent->color = RED;
            rightRoate(z->parent->parent);
        }
        else
        {
            RBNode* uncle = z->parent->parent->left;
            if (uncle && uncle->color == RED)
            {
                uncle->color             = BLACK;
                z->parent->color         = BLACK;
                z->parent->parent->color = RED;
                z                        = z->parent->parent;
            }
            else if (z == z->parent->left)
            {
                z = z->parent;
                rightRoate(z);
            }
            z->parent->color         = BLACK;
            z->parent->parent->color = RED;
            leftRoate(z->parent->parent);
        }
    }
    root->color = BLACK;
}

没有父指针的红黑树插入

插入时需要回返节点来进行修正, 若不提供父指针就需要栈来保存插入时的路径

RB-INSERT(T, z)
    y = T.nil
    x = T.root
    stack St
    while x ≠ T.nil
        y = x
        if z.key < x.key
            x = x.left
        else
            x = x.right
        St.push(y)
    if y == T.nil
        T.root = z
    elseif 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, St)

RB-INSERT-FIXUP(T, z, St)
    while z ≠ T.root and (p = St.pop()).color == RED // pop 是 top, pop 2合1
        gp = St.pop()
        if p == gp.left
            uncle = gp.right
            if uncle.color == RED
                uncle.color = BLACK
                p.color = BLACK
                gp.color = RED
                z = gp
            else
                if z = p.right
                    leftRoate(T, p)
                    swap(z, p)
                p.color = BLACK
                gp.color = RED
                rightRoate(gp)
                break
        else (same as before clause with "left" and "right" exchanged)
    T.root.color = BLACK

删除

子树替换的辅助程序

  template 
  void RBTree::transSubtree(RBNode* src, RBNode* dic)
  {
    if (!src->parent)
      root = dic;
    else if (src == src->parent->left)
      src->parent->left = dic;
    else
      src->parent->right = dic;
    if (dic) dic->parent = src->parent;
  }

删除节点 z

  1. z 的孩子小于 2 个. y = z, x = z->child
  2. z 有 2 个孩子. 两个指针 x, y; y 指向 z 的后继. x 总是指向 y 的替代者 x = y->right. 保存 y 的原始颜色
    y = successor(z), x = y->right
  template 
  void RBTree::remove(RBNode* z)
  {
    if (!z->left)
    {
      transSubtree(z, z->right);
    }
    else if (!z->right)
    {
      transSubtree(z, z->left);
    }
    else
    {
      RBNode* y = successor(z);
      RBNode* x = y->right;

      RBColor yOriginalCol = y->color;
      if (y->parent == z)
        x->parent = y;
      else
      {
        transSubtree(y, x);
        y->right         = z->right;
        y->right->parent = y;
      }
      transSubtree(z, y);
      y->left         = z->left;
      y->left->parent = y;
      delete z;
      if (yOriginalCol == BLACK) removeFix(x);
    }
  }

修复红黑树, 使其满足 5 条性质

y 的原始颜色是红色的, 则红黑树的性质仍然保持

  1. 树中黑高不变, 保持性质 5
  2. y 在新位置的颜色是 z 的颜色所以新位置, y 不会破坏性置 4. 若 y 是红色的, 则 x 是黑色的, x 替代 y 也不会破坏性置 4
  3. 明显根结点的颜色不会变, 所有结点没有多出或少颜色, 空叶子节点的颜色也不会变化. 所以性质 1,2,3 保持

y 是黑色的, 给 x 添加一个黑色

  1. 有可能产生的问题
编号 问题 解决办法
1 若 x 是根,违返了性质 1, 2 只保留 x 的一个黑色 x.color = BLACK
2 若 x 是红黑色的违返性质 1 去除 x 的红色 x.color = BLACK
3 若 x 不是根且是双黑色的, 违返了性质 1 下面
  1. 解决办法
    1. x 的兄弟节点 brother 是红色的.

      x.parent.colr = RED, brother.color = BLACK 向 x 方向旋转 x.parent

    2. x 的兄弟节点 brother 是黑色的

      • brother 的孩子都是是黑色的
        brother.color = RED;
        x = x.parent;
        
      • brother.left.color = RED, brother.right.color = BLACK
      • brother.right.colr = RED
enum RBColor { RED, BLACK };
template 
class RBNode
{
public:
    RBColor color;
    T key;
    RBNode* left;
    RBNode* right;
    RBNode* parent;
    RBNode(RBColor _color = BLACK, T _key = 0, RBNode* _left = nullptr, RBNode* _right = nullptr, RBNode* _parent = nullptr) : color(_color), key(_key), left(_left), right(_right), parent(_parent) {}
};

/**
 *  @brief 红黑树
 */

template 
class RBTree
{
private:
    RBNode* root;

public:
    RBTree() : root(nullptr) {}
    ~RBTree();
    RBTree(const RBTree& rbt);
    RBTree& operator=(const RBTree& rbt);
    /**
     *  @brief 查找键值为 k 的节点, 递归
     *  @param key 关键字
     *  @return  RBNode*
     */
    RBNode* search(T key);

    /**
     *  @brief 查找键值为 k 的节点, 非递归
     *  @param key 关键字
     *  @return  RBNode*
     */
    RBNode* iterSearch(T key);

    /**
     * @brief 插入节点
     */
    void insert(T key);

    /**
     * @brief 删除节点
     */
    void remove(T key);

    /**
     * @brief 查找节点 x (有右孩子) 的后继节点
     */
    RBNode* successor(RBNode* x);

    /**
     * @brief 返回最小值, 空树返回 0
     */
    T minimum();

    /**
     * @brief 返回最大值, 空树返回 0
     */
    T maximum();

    /**
     * @brief 中序遍历
     */
    void inOrder() const;

    /**
     * @breif 前序遍历
     */
    void preOrder() const;

private:
    /**
     * @brief 递归的拷贝函数
     */
    RBNode* copy(RBNode* parent, RBNode* _root);

    /**
     * 递归删除树
     */
    void destory(RBNode* _root);

    /**
     * @brief 左旋
     */
    void leftRoate(RBNode* x);

    /**
     *  @brief 右旋
     */
    void rightRoate(RBNode* x);

    RBNode* search(RBNode* _root, T key) const;

    void insertFix(RBNode* z);

    void transSubtree(RBNode* src, RBNode* dic);

    void removeFix(RBNode* x);

    void remove(RBNode* z);
};

template 
RBTree::RBTree(const RBTree& rbt)
{
    root = copy(nullptr, rbt.root);
}

template 
RBTree::~RBTree()
{
    destory(root);
}

template 
RBNode* RBTree::copy(RBNode* parent, RBNode* _root)
{
    if (!_root) return nullptr;
    RBNode* ret = new RBNode(_root->color, _root->key, copy(ret, _root->left), copy(ret, _root->right), parent);
}

template 
RBTree& RBTree::operator=(const RBTree& rbt)
{
    if (this == &rbt) return *this;
    destory(root);
    root = copy(nullptr, rbt.root);
}

template 
RBNode* RBTree::search(T key)
{
    return search(root, key);
}

template 
RBNode* RBTree::search(RBNode* _root, T key) const
{
    if (!_root) return nullptr;
    if (key == _root->key) return _root;
    if (key < _root->key) return search(_root->left, key);
    if (key > _root->key) return search(_root->right, key);
}

template 
RBNode* RBTree::iterSearch(T key)
{
    RBNode* pt = root;
    while (pt)
    {
        if (key == pt->key) return pt;
        if (key < pt->key)
            pt = pt->left;
        else if (key > pt->key)
            pt = pt->right;
    }
    return pt;
}

template 
void RBTree::destory(RBNode* _root)
{
    if (_root)
    {
        RBNode* _left  = _root->left;
        RBNode* _right = _root->right;
        delete _root;
        destory(_left);
        destory(_right);
    }
}

template 
RBNode* RBTree::successor(RBNode* x)
{
    RBNode* ret = x->right;
    while (ret->left)
    {
        ret = ret->left;
    }
    return ret;
}

template 
T RBTree::minimum()
{
    if (!root) return 0;
    RBNode* pt = root;
    while (pt->left) pt = pt->left;
    return pt->key;
}

template 
T RBTree::maximum()
{
    if (!root) return 0;
    RBNode* pt = root;
    while (pt->right) pt = pt->right;
    return pt->key;
}

template 
void RBTree::leftRoate(RBNode* x)
{
    RBNode* y = x->right;
    x->right     = y->left;
    if (x->right) x->right->parent = x;
    y->parent = x->parent;
    if (!y->parent)
        root = y;
    else if (y->parent->left == x)
        y->parent->left = y;
    else
        y->parent->right = y;
    y->left   = x;
    x->parent = y;
}

template 
void RBTree::rightRoate(RBNode* x)
{
    RBNode* y = x->left;
    x->left      = y->right;
    if (x->left) x->left->parent = x;
    y->parent = x->parent;
    if (!y->parent)
        root = y;
    else if (y->parent->left == x)
        y->parent->left = y;
    else
        y->parent->right = y;
    y->right  = x;
    x->parent = y;
}

template 
void RBTree::insert(T key)
{
    RBNode* z  = new RBNode(RED, key, nullptr, nullptr, nullptr);
    RBNode* px = root;
    RBNode* py = nullptr;
    while (px)
    {
        py = px;
        if (key < px->key)
            px = px->left;
        else
            px = px->right;
    }
    z->parent = py;
    if (!py)
        root = z;
    else if (key < py->key)
        py->left = z;
    else
        py->right = z;
    insertFix(z);
}

template 
void RBTree::insertFix(RBNode* z)
{
    while (z->parent && z->parent->color == RED)
    {
        if (z->parent == z->parent->parent->left)
        {
            RBNode* uncle = z->parent->parent->right;
            if (uncle && uncle->color == RED)
            {
                uncle->color             = BLACK;
                z->parent->color         = BLACK;
                z->parent->parent->color = RED;
                z                        = z->parent->parent;
                continue;
            }
            else if (z == z->parent->right)
            {
                z = z->parent;
                leftRoate(z);
            }
            z->parent->color         = BLACK;
            z->parent->parent->color = RED;
            rightRoate(z->parent->parent);
        }
        else
        {
            RBNode* uncle = z->parent->parent->left;
            if (uncle && uncle->color == RED)
            {
                uncle->color             = BLACK;
                z->parent->color         = BLACK;
                z->parent->parent->color = RED;
                z                        = z->parent->parent;
                continue;
            }
            else if (z == z->parent->left)
            {
                z = z->parent;
                rightRoate(z);
            }
            z->parent->color         = BLACK;
            z->parent->parent->color = RED;
            leftRoate(z->parent->parent);
        }
    }
    root->color = BLACK;
}

template 
void RBTree::transSubtree(RBNode* src, RBNode* dic)
{
    if (!src->parent)
        root = dic;
    else if (src == src->parent->left)
        src->parent->left = dic;
    else
        src->parent->right = dic;
    if (dic) dic->parent = src->parent;
}

template 
void RBTree::remove(T key)
{
    RBNode* pt = root;
    while (key != pt->key)
    {
        if (key < pt->key)
            pt = pt->left;
        else
            pt = pt->right;
    }
    remove(pt);
}

template 
void RBTree::remove(RBNode* z)
{
    RBNode* y = z;
    RBNode* x;
    RBColor yOriginalCol = y->color;
    if (!z->left)
    {
        x = z->right;
        transSubtree(z, x);
    }
    else if (!z->right)
    {
        x = z->left;
        transSubtree(z, x);
    }
    else
    {
        y            = successor(z);
        yOriginalCol = y->color;
        x            = y->right;
        if (y->parent == z)
            x->parent = y;
        else
        {
            transSubtree(y, x);
            y->right         = z->right;
            y->right->parent = y;
        }
        transSubtree(z, y);
        y->left         = z->left;
        y->left->parent = y;
    }
    delete z;
    if (yOriginalCol == BLACK) removeFix(x);
}

template 
void RBTree::removeFix(RBNode* x)
{
    if (x != root && x->color == BLACK)
    {
        if (x == x->parent->left)
        {
            RBNode* brother = x->parent->right;
            if (brother->color == RED)
            {
                brother->color   = BLACK;
                x->parent->color = RED;
                leftRoate(x->parent);
                brother = x->parent->right;
            }
            if (brother->left->color == BLACK && brother->right->color == BLACK)
            {
                brother->color = RED;
                x              = x->parent;
            }
            else if (brother->right->color == BLACK)
            {
                brother->left->color = BLACK;
                brother->color       = RED;
                rightRoate(brother);
                brother = x->parent->right;
            }
            brother->color        = x->parent->color;
            x->parent->color      = BLACK;
            brother->right->color = BLACK;
            leftRoate(x->parent);
            x = root;
        }
        else
        {
            RBNode* brother = x->parent->left;
            if (brother->color == RED)
            {
                brother->color   = BLACK;
                x->parent->color = RED;
                rightRoate(x->parent);
                brother = x->parent->left;
            }
            if (brother->left->color == BLACK && brother->right->color == BLACK)
            {
                brother->color = RED;
                x              = x->parent;
            }
            else if (brother->left->color == BLACK)
            {
                brother->right->color = BLACK;
                brother->color        = RED;
                leftRoate(brother);
                brother = x->parent->left;
            }
            brother->color       = x->parent->color;
            x->parent->color     = BLACK;
            brother->left->color = BLACK;
            rightRoate(x->parent);
            x = root;
        }
    }
    x->color = BLACK;
}
template 
void RBTree::preOrder() const
{
    using std::cout;
    using std::endl;
    using std::stack;
    stack*> St;
    RBNode* pt = root;
    while (pt || !St.empty())
    {
        while (pt)
        {
            cout << pt->key << ",";
            St.push(pt);
            pt = pt->left;
        }
        pt = St.top();
        St.pop();
        pt = pt->right;
    }
    cout << endl;
}

template 
void RBTree::inOrder() const
{
    using std::cout;
    using std::endl;
    using std::stack;
    stack*> St;
    RBNode* pt = root;
    while (pt || !St.empty())
    {
        while (pt)
        {
            St.push(pt);
            pt = pt->left;
        }
        pt = St.top();
        cout << pt->key << ",";
        St.pop();
        pt = pt->right;
    }
    cout << endl;
}

你可能感兴趣的:(红黑树)