算法与数据结构☞自平衡二叉树☞红黑树

210 阅读1分钟

红黑树

  1. 是一棵二叉排序树;
  2. 节点要么是红色要么是黑色,根节点是黑色,叶子节点也是黑色;
  3. 红色节点的子节点必须是黑色;
  4. 从根节点任意路径向下到叶子节点途经的黑色节点个数相同(适用子树);
#include <iostream>

enum class RbColor {RB_RED, RB_BLACK};

template <typename T>
class RbNode {
public:
    RbNode<T>* parent;
    RbNode<T>* left;
    RbNode<T>* right;
    T data;
    RbColor color;
    RbNode() : parent(nullptr), left(nullptr), right(nullptr), color(RbColor::RB_BLACK) {}
    RbNode(RbNode<T>* p, RbNode<T>* l, RbNode<T>* r, T d, RbColor c) : parent(p), left(l), right(r), data(d), color(c) {}
};

template<typename T>
class RbTree {
public:
    RbTree() {
        root = NIL;
    }
    void Insert(T data);
private:
    RbNode<T>* L(RbNode<T>* node);
    RbNode<T>* R(RbNode<T>* node);
    RbNode<T>* root;
    static RbNode<T>* NIL;
    static RbNode<T> nullobj;
};
template<typename T>
RbNode<T> RbTree<T>::nullobj = RbNode<T>();

template<typename T>
RbNode<T>* RbTree<T>::NIL = &RbTree<T>::nullobj;

template<typename T>
void RbTree<T>::Insert(T data) {
    RbNode<T>* cur = root;
    RbNode<T>* pcur = nullptr;
    RbNode<T>* uncle = nullptr;
    RbNode<T>* gp = nullptr;
    if(root == NIL) {
        root = new RbNode<T>(nullptr, NIL, NIL, data, RbColor::RB_BLACK);
        return;
    }
    while(cur->left != NIL || cur->right != NIL) {
        if(data < cur->data) {
            cur = cur->left;
        }
        else if(data > cur->data) {
            cur = cur->right;
        }
        else {
            return;
        }
    }
    if(data < cur->data) {
        cur->left = new RbNode<T>(cur, NIL, NIL, data, RbColor::RB_RED);
        pcur = cur;
        cur = cur->left;
    }
    else {
        cur->right = new RbNode<T>(cur, NIL, NIL, data, RbColor::RB_RED);
        pcur = cur;
        cur = cur->right;
    }
    while(pcur != nullptr && pcur->color == RbColor::RB_RED) {
        gp = pcur->parent;
        uncle = gp->left == pcur ? gp->right : gp->left;
        if(uncle->color == RbColor::RB_RED) {
            pcur->color = RbColor::RB_BLACK;
            uncle->color = RbColor::RB_BLACK;
            gp->color = RbColor::RB_RED;
            cur = gp;
            pcur = cur->parent;
        }
        else {
            if(gp->left == pcur && pcur->left == cur) {
                pcur->color = RbColor::RB_BLACK;
                gp->color = RbColor::RB_RED;
                gp = R(gp);
            }
            else if(gp->right == pcur && pcur->right == cur) {
                pcur->color = RbColor::RB_BLACK;
                gp->color = RbColor::RB_RED;
                gp = L(gp);
            }
            else if(gp->left == pcur && pcur->right == cur) {
                pcur = L(pcur);
                pcur->color = RbColor::RB_BLACK;
                gp->color = RbColor::RB_RED;
                gp = R(gp);
            }
            else {
                pcur = R(pcur);
                pcur->color = RbColor::RB_BLACK;
                gp->color = RbColor::RB_RED;
                gp = L(gp);
            }
        }
    }
    root->color = RbColor::RB_BLACK;
}

template<typename T>
RbNode<T>* RbTree<T>::L(RbNode<T>* node) {
    RbNode<T>* t1 = node->left;
    RbNode<T>* t2 = node->right;
    
    node->right->left = node;
    node->parent = t2;
    
    node->right = t1;
    t1->parent = node;
    
    return t2;
}

template<typename T>
RbNode<T>* RbTree<T>::R(RbNode<T>* node) {
    RbNode<T>* t1 = node->right;
    RbNode<T>* t2 = node->left;
    
    node->left->right = node;
    node->parent = t2;
    
    node->left = t1;
    t1->parent = node;
    
    return t2;
}