RBT

RBT#

  • 是一种特化的AVL; 节点非黑即红; 根节点一定是黑色; 叶子节点(NIL)一定是黑色; 每个红色节点的两个子节点都为黑色; 从任一节点到其每个叶子的所有路径, 都包含相同数目的黑色节点

RBT&AVL#

  • RBT本身并不是100%平衡, 但是仅考虑其黑色子节点, RBT是平衡的
  • RBT相对于AVL插入/删除节点不会频繁的旋转, 用非严格的平衡来换取增删节点时候旋转次数的降低, 任何不平衡都会在三次旋转之内解决
  • AVL是严格平衡树(高度平衡的BRT), 因此在增加或者删除节点的时候, 根据不同情况, 旋转的次数比红黑树要多
  • 红黑树的插入/删除效率更高, AVL查找性能更优

_data_struct#

typedef struct rbt_node_s  rbt_node_t;

struct rbt_node_s {
    rbt_key_t       key;
    rbt_node_t     *left;
    rbt_node_t     *right;
    rbt_node_t     *parent;
    u_char                 color;
    u_char                 data;
};


typedef struct rbt_s  rbt_t;

typedef void (*rbt_insert_pt) (rbt_node_t *root,
    rbt_node_t *node, rbt_node_t *sentinel);

struct rbt_s {
    rbt_node_t     *root;
    rbt_node_t     *sentinel;
    rbt_insert_pt   insert;
};

_insert#

/*
if root is nil
    insert node to root and change to black
    return
insert a red node
loop if node not root && father is red:
    switch :
        case 1, father is black: 
            nothing todo
        case 2, father is red, uncle is red: 
            father and uncle change to black
            grandfather change to red
            now start to fix balance from grandfather, grandfather change to node
            continue loop
        case 3, father is red, uncle is black: 
            if (node is left child and father is right child) or (node is left right and father is left child)
                rotate father
            father change to black
            grandfather change to red
            rotate grandfather
change root to black 
*/
void
rbtree_insert(rbtree_t *tree, rbtree_node_t *node)
{
    rbtree_node_t  **root, *temp, *sentinel;

    /* a binary tree insert */

    root = &tree->root;
    sentinel = tree->sentinel;

    if (*root == sentinel) {
        node->parent = NULL;
        node->left = sentinel;
        node->right = sentinel;
        rbt_black(node);
        *root = node;

        return;
    }

    tree->insert(*root, node, sentinel);

    /* re-balance tree */

    while (node != *root && rbt_is_red(node->parent)) {

        if (node->parent == node->parent->parent->left) {
            temp = node->parent->parent->right;

            if (rbt_is_red(temp)) {
                rbt_black(node->parent);
                rbt_black(temp);
                rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->right) {
                    node = node->parent;
                    rbtree_left_rotate(root, sentinel, node);
                }

                rbt_black(node->parent);
                rbt_red(node->parent->parent);
                rbtree_right_rotate(root, sentinel, node->parent->parent);
            }

        } else {
            temp = node->parent->parent->left;

            if (rbt_is_red(temp)) {
                rbt_black(node->parent);
                rbt_black(temp);
                rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->left) {
                    node = node->parent;
                    rbtree_right_rotate(root, sentinel, node);
                }

                rbt_black(node->parent);
                rbt_red(node->parent->parent);
                rbtree_left_rotate(root, sentinel, node->parent->parent);
            }
        }
    }

    rbt_black(*root);
}

Time Complexity#

  • best: O(log(n))
  • worst: O(log(n))

_delete#

/*
delete node as rbt
    find subst where is used to replace node
    find temp whitch is used to replace subst
    use temp replace subst
    use subst replace node
if subst is red
    red node don't effect balance, no need to balance
    return
subst is black and subst has move, so need to balance
balance
    loop if temp not root && temp is black
        if temp is left child
            w is the brother of temp 
            if w is red
                w change to black
                temp's parent change to red(black ->red)
                left rotate temp's parent
                w update
                now w is not red
            if w is black && w's childs are black
                w change to red
                temp change to temp's parent(if temp is red, break the loop; temp change to red)
            if w is blcak && w's left child is red && w's right child is black
                w's left child change to black
                w change to red
                right rotate w
                update w
                now w is black && w's right child is red
            if w is black && w's right child is red
                w change to the color of temp's parent
                temp's parent change to black
                w's right child change to black
                right rotate w
                now balance(the side of temp add a black, so balance)
        if temp is right child
            ...
temp change to black
*/
void
rbtree_delete(rbtree_t *tree, rbtree_node_t *node)
{
    uint_t           red;
    rbtree_node_t  **root, *sentinel, *subst, *temp, *w;

    /* a binary tree delete */

    root = &tree->root;
    sentinel = tree->sentinel;

    if (node->left == sentinel) {
        temp = node->right;
        subst = node;

    } else if (node->right == sentinel) {
        temp = node->left;
        subst = node;

    } else {
        subst = rbtree_min(node->right, sentinel);
        temp = subst->right;
    }

    if (subst == *root) {
        *root = temp;
        rbt_black(temp);

        /* DEBUG stuff */
        node->left = NULL;
        node->right = NULL;
        node->parent = NULL;
        node->key = 0;

        return;
    }

    red = rbt_is_red(subst);

    if (subst == subst->parent->left) {
        subst->parent->left = temp;

    } else {
        subst->parent->right = temp;
    }

    if (subst == node) {

        temp->parent = subst->parent;

    } else {

        if (subst->parent == node) {
            temp->parent = subst;

        } else {
            temp->parent = subst->parent;
        }

        subst->left = node->left;
        subst->right = node->right;
        subst->parent = node->parent;
        rbt_copy_color(subst, node);

        if (node == *root) {
            *root = subst;

        } else {
            if (node == node->parent->left) {
                node->parent->left = subst;
            } else {
                node->parent->right = subst;
            }
        }

        if (subst->left != sentinel) {
            subst->left->parent = subst;
        }

        if (subst->right != sentinel) {
            subst->right->parent = subst;
        }
    }

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;

    if (red) {
        return;
    }

    /* a delete fixup */

    while (temp != *root && rbt_is_black(temp)) {

        if (temp == temp->parent->left) {
            w = temp->parent->right;

            if (rbt_is_red(w)) {
                rbt_black(w);
                rbt_red(temp->parent);
                rbtree_left_rotate(root, sentinel, temp->parent);
                w = temp->parent->right;
            }

            if (rbt_is_black(w->left) && rbt_is_black(w->right)) {
                rbt_red(w);
                temp = temp->parent;

            } else {
                if (rbt_is_black(w->right)) {
                    rbt_black(w->left);
                    rbt_red(w);
                    rbtree_right_rotate(root, sentinel, w);
                    w = temp->parent->right;
                }

                rbt_copy_color(w, temp->parent);
                rbt_black(temp->parent);
                rbt_black(w->right);
                rbtree_left_rotate(root, sentinel, temp->parent);
                temp = *root;
            }

        } else {
            w = temp->parent->left;

            if (rbt_is_red(w)) {
                rbt_black(w);
                rbt_red(temp->parent);
                rbtree_right_rotate(root, sentinel, temp->parent);
                w = temp->parent->left;
            }

            if (rbt_is_black(w->left) && rbt_is_black(w->right)) {
                rbt_red(w);
                temp = temp->parent;

            } else {
                if (rbt_is_black(w->left)) {
                    rbt_black(w->right);
                    rbt_red(w);
                    rbtree_left_rotate(root, sentinel, w);
                    w = temp->parent->left;
                }

                rbt_copy_color(w, temp->parent);
                rbt_black(temp->parent);
                rbt_black(w->left);
                rbtree_right_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        }
    }

    rbt_black(temp);
}

## Time Complexity#

  • best: O(log(n))
  • worst: O(log(n))