数据结构与算法分析:红黑树

来自 红黑树(四)之 C++的实现

#include <iostream>
#include <iomanip>
using namespace std;

template<class T>
class RBTree{
    //红黑树,最坏情形O(logN),图示见 https://www.cnblogs.com/skywang12345/p/3245399.html
    //满足下面性质的二分查找树
    //(0.nullptr节点视为黑色)
    //1.节点是红色或黑色
    //2.整棵树的根是黑色
    //3.如果一个节点是红色,子节点必须是黑色
    //4.从一个节点到一个nullptr指针的每一条路径必须包含相同数目的黑色节点

    //红黑树的高度最多是2log(N+1),保证查找是对数操作

    #define rb_parent(r)   ((r)->parent)
    #define rb_color(r) ((r)->color)
    #define rb_is_red(r)   ((r)->color==RED)
    #define rb_is_black(r)  ((r)->color==BLACK)
    #define rb_set_black(r)  do { (r)->color = BLACK; } while (0)
    #define rb_set_red(r)  do { (r)->color = RED; } while (0)
    #define rb_set_parent(r,p)  do { (r)->parent = (p); } while (0)
    #define rb_set_color(r,c)  do { (r)->color = (c); } while (0)


private:
    enum RBTColor{RED,BLACK};
    struct RBTNode{
        RBTColor color;
        T data;
        RBTNode* left;
        RBTNode* right;
        RBTNode* parent;
        RBTNode(T v,RBTColor c,RBTNode* l,RBTNode* r,RBTNode* p):data(v),left(l),right(r),parent(p),color(c){};
    };
    RBTNode* root;
    void inOrderTraversal(RBTNode* node){
        if (!node) return;
        inOrderTraversal(node->left);
        cout << node->data << ' ';
        inOrderTraversal(node->right);
    }

    void print(RBTNode* tree,T v,int direction){
        if (tree){
            if (direction==0) cout << setw(2) << tree->data << "(B) is root" << endl;
            else cout << setw(2) << tree->data <<  (rb_is_red(tree)?"(R)":"(B)") << " is " << setw(2) << v << "'s "  << setw(12) << (direction==1?"right child" : "left child") << endl;
        }
        if (tree->left) print(tree->left,tree->data,-1);
        if (tree->right) print(tree->right,tree->data,  1);
    }

    //插入叶子节点应该是红色,因为如果是黑色就会违背性质4
    //下面如果其父节点是黑色可以直接结束,如果是红色必须调整树使其满足性质3
    //上面链接中的原文分析得很精彩,不懂why可以去看

    //对x进行左旋=>x的右子节点代替x,x成为其左子节点
    //对x进行右旋=>x的左子节点代替x,x成为其右子节点

    void leftRotate(RBTNode* &root, RBTNode* x){
        // 设置x的右孩子为y
        RBTNode *y = x->right;

        // 将 “y的左孩子” 设为 “x的右孩子”;
        // 如果y的左孩子非空,将 “x” 设为 “y的左孩子的父亲”
        x->right = y->left;
        if (y->left) y->left->parent = x;

        // 将 “x的父亲” 设为 “y的父亲”
        y->parent = x->parent;

        if (!x->parent) root = y;   // 如果 “x的父亲” 是空节点,则将y设为根节点
        else{
            if (x->parent->left == x) x->parent->left = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
            else x->parent->right = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
        }

        // 将 “x” 设为 “y的左孩子”
        y->left = x;
        // 将 “x的父节点” 设为 “y”
        x->parent = y;
    }


/*
 * 对红黑树的节点(y)进行右旋转
 *
 * 右旋示意图(对节点y进行左旋):
 *            py                               py
 *           /                                /
 *          y                                x
 *         /  \      --(右旋)-->            /  \                     #
 *        x   ry                           lx   y
 *       / \                                   / \                   #
 *      lx  rx                                rx  ry
 *
 */
    void rightRotate(RBTNode* &root, RBTNode* y){
        // 设置x是当前节点的左孩子。
        RBTNode *x = y->left;

        // 将 “x的右孩子” 设为 “y的左孩子”;
        // 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲”
        y->left = x->right;
        if (x->right) x->right->parent = y;

        // 将 “y的父亲” 设为 “x的父亲”
        x->parent = y->parent;

        if (!y->parent) root = x;            // 如果 “y的父亲” 是空节点,则将x设为根节点
        else{
            if (y == y->parent->right) y->parent->right = x;    // 如果 y是它父节点的右孩子,则将x设为“y的父节点的右孩子”
            else y->parent->left = x;    // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子”
        }

        // 将 “y” 设为 “x的右孩子”
        x->right = y;

        // 将 “y的父节点” 设为 “x”
        y->parent = x;
    }


    //插入的叶子结点(当前节点)是红色,父节点也是红色可分为下面三种情况:
    //1.叔叔节点(父亲的兄弟节点)也是红色:父变黑.叔变黑,祖父变红,将祖父设为当前节点
    //2.叔叔节点(父亲的兄弟节点)是黑色,且待插入节点是挂在了右边:将父节点设为当前节点,当前节点左旋(这样插入的节点代替了原来的父节点)
    //3.叔叔节点(父亲的兄弟节点)是黑色,且待插入节点是挂在了左边:父变黑,祖父变红,祖父节点右旋

    void insert(RBTNode* &root,RBTNode* node){
        RBTNode* parent=nullptr;
        RBTNode* cur=root;
        while (cur){
            parent=cur;        //保存路径的上一个顶点,找到要插入的位置的父节点
            if (node->data<cur->data) cur=cur->left;
            else cur=cur->right;
        }
        node->parent=parent;
        if (parent){
            if (node->data<parent->data) parent->left=node;
            else parent->right=node;
        }
        else root=node;

        node->color=RED;
        insertAdjust(root,node);  //调整成红黑树
    }
    void insertAdjust(RBTNode* &root,RBTNode* node){
        RBTNode* parent,*gparent;
        while ((parent=rb_parent(node)) && rb_is_red(parent)){
            //父节点存在且是红色
            gparent=rb_parent(parent);
            if (parent==gparent->left){
                RBTNode* uncle=gparent->right;
                if (uncle && rb_is_red(uncle)){
                    //情况1
                    rb_set_black(parent);
                    rb_set_black(uncle);
                    rb_set_red(gparent);
                    node=gparent;
                }
                else if (parent->right==node){
                    //情况2
                    leftRotate(root,parent);
                    RBTNode* tmp=parent;
                    parent=node;
                    node=tmp;
                }

                //情况3
                rb_set_black(parent);
                rb_set_red(gparent);
                rightRotate(root,gparent);
            }
            else{
                RBTNode* uncle = gparent->left;
                if (uncle && rb_is_red(uncle)){
                    if (uncle && rb_is_red(uncle)){
                        //情况1
                        rb_set_black(uncle);
                        rb_set_black(parent);
                        rb_set_red(gparent);
                        node = gparent;
                        continue;
                    }
                }
                else if (parent->left == node){
                    //情况2
                    RBTNode* tmp;
                    rightRotate(root, parent);
                    tmp = parent;
                    parent = node;
                    node = tmp;
                }
                //情况3
                rb_set_black(parent);
                rb_set_red(gparent);
                leftRotate(root, gparent);
            }
        }
        rb_set_black(root);
    }

    RBTNode* search(RBTNode* x, T v) const{
        if (!x || x->data==v) return x;
        if (v < x->data) return search(x->left, v);
        else return search(x->right, v);
    }

    //删除节点(与二叉搜索树操作一样)之后调整成红黑树
    void remove(RBTNode* &root, RBTNode *node){
        RBTNode *child, *parent;
        RBTColor color;

        if ((node->left) && (node->right)){
            RBTNode *replace = node;

            replace = replace->right;
            while (replace->left) replace = replace->left; //右子树的最小节点代替

            if (rb_parent(node)){
                if (rb_parent(node)->left == node) rb_parent(node)->left = replace;
                else rb_parent(node)->right = replace;
            }
            else root = replace;

            child = replace->right;
            parent = rb_parent(replace);

            color = rb_color(replace);


            if (parent == node) parent = replace;
            else{
                if (child) rb_set_parent(child, parent);
                parent->left = child;
                replace->right = node->right;
                rb_set_parent(node->right, replace);
            }

            replace->parent = node->parent;
            replace->color = node->color;
            replace->left = node->left;
            node->left->parent = replace;

            if (color == BLACK) removeAdjust(root, child, parent);

            delete node;
            return ;
        }

        if (node->left) child = node->left;
        else child = node->right;

        parent = node->parent;
        color = node->color;

        if (child) child->parent = parent;

        if (parent){
            if (parent->left == node) parent->left = child;
            else parent->right = child;
        }
        else root = child;
        if (color == BLACK) removeAdjust(root, child, parent);
        delete node;
    }

    void removeAdjust(RBTNode* &root, RBTNode *node, RBTNode *parent){
        RBTNode *other;

        while ((!node || rb_is_black(node)) && node != root){
            if (parent->left == node){
                other = parent->right;
                if (rb_is_red(other)){
                    // Case 1: x的兄弟w是红色的
                    rb_set_black(other);
                    rb_set_red(parent);
                    leftRotate(root, parent);
                    other = parent->right;
                }
                if ((!other->left || rb_is_black(other->left)) && (!other->right || rb_is_black(other->right))){
                    // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
                    rb_set_red(other);
                    node = parent;
                    parent = rb_parent(node);
                }
                else{
                    if (!other->right || rb_is_black(other->right)){
                        // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
                        rb_set_black(other->left);
                        rb_set_red(other);
                        rightRotate(root, other);
                        other = parent->right;
                    }
                    // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                    rb_set_color(other, rb_color(parent));
                    rb_set_black(parent);
                    rb_set_black(other->right);
                    leftRotate(root, parent);
                    node = root;
                    break;
                }
            }
            else{
                other = parent->left;
                if (rb_is_red(other)){
                    // Case 1: x的兄弟w是红色的
                    rb_set_black(other);
                    rb_set_red(parent);
                    rightRotate(root, parent);
                    other = parent->left;
                }
                if ((!other->left || rb_is_black(other->left)) && (!other->right || rb_is_black(other->right))){
                    // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
                    rb_set_red(other);
                    node = parent;
                    parent = rb_parent(node);
                }
                else{
                    if (!other->left || rb_is_black(other->left)){
                        // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
                        rb_set_black(other->right);
                        rb_set_red(other);
                        leftRotate(root, other);
                        other = parent->left;
                    }
                    // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                    rb_set_color(other, rb_color(parent));
                    rb_set_black(parent);
                    rb_set_black(other->left);
                    rightRotate(root, parent);
                    node = root;
                    break;
                }
            }
        }
        if (node) rb_set_black(node);
    }

    public:
        RBTree():root(nullptr){};
        void inOrderTraversal(){inOrderTraversal(root);}
        void insert(T v){
            RBTNode* z=new RBTNode(v,BLACK,nullptr,nullptr,nullptr);
            insert(root,z);
        }
        void remove(T v){
            RBTNode* node;
            if ((node = search(root, v))) remove(root, node);
        }
        void print(){
            if (root) print(root,root->data,0);
        }


};

int main()
{
    int a[]= {10, 40, 30, 60, 90, 70, 20, 50, 80};
    int check_insert=1;    // "插入"动作的检测开关(0,关闭;1,打开)
    int check_remove=1;    // "删除"动作的检测开关(0,关闭;1,打开)
    int i;
    int ilen = (sizeof(a)) / (sizeof(a[0])) ;
    RBTree<int>* tree=new RBTree<int>();

    cout << "== 原始数据: ";
    for(i=0; i<ilen; i++)
        cout << a[i] <<" ";
    cout << endl;

    for(i=0; i<ilen; i++)
    {
        tree->insert(a[i]);
        // 设置check_insert=1,测试"添加函数"
        if(check_insert)
        {
            cout << "== 添加节点: " << a[i] << endl;
            cout << "== 树的详细信息: " << endl;
            tree->print();
            cout << endl;
        }

    }

    cout << "\n== 中序遍历: ";
    tree->inOrderTraversal();


    cout << "== 树的详细信息: " << endl;
    tree->print();

    // 设置check_remove=1,测试"删除函数"
    if(check_remove)
    {
        for(i=0; i<ilen; i++)
        {
            tree->remove(a[i]);

            cout << "== 删除节点: " << a[i] << endl;
            cout << "== 树的详细信息: " << endl;
            tree->print();
            cout << endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值