BST - 红黑树

#include<bits/stdc++.h>
using namespace std;

struct RBTreeNode {
    bool black;
    int val;
    RBTreeNode *left,*right,*parent;
    RBTreeNode(int v = 0) {
        val = v;
        black = false;
        left = right = parent = NULL;
    }
};
struct RBTree {
private:
    RBTreeNode *root;

    void leftRoate(RBTreeNode*node) {
        RBTreeNode*tmp = node->left;//tmp可能为NULL
        RBTreeNode*parent = node->parent;
        RBTreeNode*grandpa = parent->parent;

        node->left = parent;
        parent->right = tmp;

        if(tmp) tmp->parent = parent;
        parent->parent = node;
        node->parent = grandpa;
        if(!grandpa) { 
            root = node;
            return;
        }
        if(grandpa->left == parent) grandpa->left = node;
        else grandpa->right = node;
    }
    void rightRoate(RBTreeNode*node) { //《不要随便传引用!!!》-- RBTreeNode*&node 在旋转时传入node->parent->left
        RBTreeNode*tmp = node->right;         //然后第六行赋值parent->left = tmp(tmp == node) 直接导致node<-NULL,段错误找了好久
        RBTreeNode*parent = node->parent;
        RBTreeNode*grandpa = parent->parent;

        node->right= parent;
        parent->left= tmp;

        if(tmp) tmp->parent = parent;//tmp可能为NULL,这里段错误找了好久
        parent->parent = node;
        node->parent = grandpa;
        if(!grandpa) {     //如果改变了根要把树的根给改变了,不然会出现只剩一个根的情况*********这里出错找了好久
            root = node;
            return;
        }
        if(grandpa->left == parent) grandpa->left = node;
        else grandpa->right = node;
    }

    void insertAdjust(RBTreeNode *root) {
        if(!root->parent) { //当前插入节点为根,变为黑
            root->black = true;
            return;
        }
        RBTreeNode* parent = root->parent;
        if(parent->black) {    //红连黑,什么都不用做
            return;
        }
        RBTreeNode* &grandpa = parent->parent;    //父节点为红,必不为根
        //assert(grandpa && grandpa->black);
        if(grandpa->left && grandpa->right && !grandpa->left->black && !grandpa->right->black) { 
            //祖父节点为黑,其两个儿子节点为红,祖父节点变红,儿子节点变黑,往上调整
            grandpa->black = false;
            grandpa->left->black = grandpa->right->black = true;
            insertAdjust(grandpa);
            return;
        }
        if(grandpa->right == parent){
            if(parent->left == root) {
                rightRoate(root);
            } else {
                root = root->parent;
            }
            leftRoate(root);
            swap(root->black,root->left->black);
            return;
        }
        if(grandpa->left == parent) {
            if(parent->right == root) {
                leftRoate(root);
            } else {
                root = root->parent;
            }
            rightRoate(root);
            swap(root->black,root->right->black);
            return;
        }
        //assert(0);
    }

    void insert(RBTreeNode *parent,RBTreeNode *&root,int val) {
        if(!root) {
            root = new RBTreeNode(val);
            root->parent = parent;
            insertAdjust(root);
            return;
        }
        //printf("root:%p left:%p right:%p parent:%p val:%d black:%d\n",root,root->left,root->right,root->parent,root->val,root->black);
        if(val > root->val) {
            insert(root,root->right,val);
        }
        else {
            insert(root,root->left,val);
        }
    }

    RBTreeNode* begin(RBTreeNode *root) {
        while(root && root->left) root = root->left;
        return root;
    }

    RBTreeNode* next(RBTreeNode *root) {
        if(root->right) {
            root = root->right;
            while(root->left) root = root->left;
            return root;
        }
        while(root->parent && root->parent->right == root) root = root->parent;
        return root->parent;
    }

    int check(RBTreeNode *root) {
        if(!root) return 0;
        if(root->left) {
            assert(!(!root->black && !root->left->black));
            assert(root->left->parent == root);
            assert(root->left->val <= root->val);
        }
        if(root->right) {
            assert(root->right->parent == root);
            assert(root->right->val >= root->val);
        }
        int a = check(root->left);
        int b = check(root->right);
        assert(a == b);
        return a + root->black;
    }

    bool erase(RBTreeNode *&root,RBTreeNode *node) {
        if(!node) return false;
        if(node->left && node->right) { //两个子节点,拿左儿子的最右儿子或右儿子的最左儿子复制到要删除的节点
            RBTreeNode *tmp = node->left;
            while(tmp->right) tmp = tmp->right;//取左儿子的最右儿子
            node->val = tmp->val; //copy
            node = tmp;
        }
        if(!node->black) { //被删除节点为红->这个节点不可能为根,直接删除即可
            RBTreeNode*child = node->left;
            RBTreeNode*parent = node->parent;
            if(child) child->parent = parent;
            assert(parent);
            if(parent->left == node) parent->left = child;
            else parent->right = child;
            delete node;
            return true;
        }
        RBTreeNode *child=NULL;
        if(node->left) {
            child = node->left;
        } else if(node->right) {
            child = node->right;
        }
        RBTreeNode *parent = node->parent;
        if(child) child->parent = parent;

        if(!parent) root = child;
        else if(parent->left == node) parent->left = child;
        else parent->right = child;
        eraseAdjust(child,parent);
        delete node;
        return true;
    }

    void eraseAdjust(RBTreeNode *node,RBTreeNode *parent) {
        if(!parent) {    
            //1.1 子节点为根,染为黑
            if(node) node->black = true;
            return;
        }
        if(node && !node->black) { 
            //1.2子节点为红,直接染为黑
            node->black = true;
            return;
        }

        RBTreeNode *brother = (parent->left == node ? parent->right : parent->left);
        if(!parent->black) {    //2.父节点为红,兄弟节点必为黑
            assert((!brother||brother->black));
            if((!brother->left || brother->left->black) && (!brother->right || brother->right->black)) {
                //2.1 兄弟节点两个儿子为 black,black
                swap(brother->black,parent->black);
                return;
            }
            if(parent->left == node) {
                if(brother && brother->left && !brother->left->black) {    
                    //2.2 兄弟节点两个儿子为 red,?
                    parent->black = true;
                    rightRoate(brother->left);
                    leftRoate(parent->right);
                    return;
                }
                //2.3 兄弟节点两个儿子为 black,red
                leftRoate(brother);
                return;
            } else {
                if(brother && brother->right && !brother->right->black) {    
                    //2.2 兄弟节点两个儿子为 ?,red
                    parent->black = true;
                    leftRoate(brother->right);
                    rightRoate(parent->left);
                    return;
                }
                //2.3 兄弟节点两个儿子为 red,black
                rightRoate(brother);
                return;
            }
        }
        //3.父节点为黑
        if(brother && !brother->black) { 
            //3.1 兄弟节点为红,两个儿子节点必为黑
            swap(parent->black,brother->black);
            if(parent->left == node) leftRoate(brother);
            else rightRoate(brother);
            eraseAdjust(node,parent);    //处理后node路径上还是少一个黑色节点,重新调整
            return;
        }

        //3.2 兄弟节点为黑
        assert(brother);    //brother必不为nil,否则两边黑节点个数不一样
        if((!brother->left||brother->left->black) && (!brother->right||brother->right->black)) {
            //3.2.1 两个儿子节点为黑
            brother->black = false;
            eraseAdjust(parent,parent->parent);
            return;
        }
        if(parent->left == node) {
            if(brother->left && !brother->left->black) { 
                //3.2.2 兄弟节点左儿子为红
                brother->left->black = true;
                rightRoate(brother->left);
                leftRoate(parent->right);
                return;
            }
            //3.2.3 兄弟节点儿子为 black,red
            brother->right->black = true;
            leftRoate(brother);
            return;
        } else {
            if(brother->right && !brother->right->black) { 
                //3.2.2 兄弟节点左儿子为红
                brother->right->black = true;
                leftRoate(brother->right);
                rightRoate(parent->left);
                return;
            }
            //3.2.3 兄弟节点儿子为 black,red
            brother->left->black = true;
            rightRoate(brother);
            return;
        }
    }

    RBTreeNode* find(RBTreeNode *root,int val) {
        while(root && root->val != val) {
            if(root->val > val) root = root->left;
            else root = root->right;
        }
        return root;
    }
public:
    RBTree() { root = NULL; }
    void insert(int x) {
        insert(NULL,root,x);
    }
    void print() {
        for(RBTreeNode *it = begin(root);it;) {
            printf("%d",it->val);
            it = next(it);
            if(!it) printf("\n");
            else printf(" ");
        }
        /*for(RBTreeNode *it = begin(root);it;it=next(it)) {
            printf("self:%p parent:%p left:%p right:%p val:%d black:%d\n",it,it->parent,it->left,it->right,it->val,it->black);
        }*/
    }
    RBTreeNode* begin() {
        return begin(root);
    }
    RBTreeNode* next() {
        return next(root);
    }
    int check() {
        check(root);
    }
    RBTreeNode* find(int val) {
        return find(root,val);
    }
    bool erase(RBTreeNode *node) {
        return erase(root,node);
    }
};


int main() {
    int n;
    while(scanf("%d",&n)==1) {
        RBTree a;
        vector<int>arr;
        for(int i=0,x;i<n;i++) {
            //scanf("%d",&x);
            x = rand();
            arr.push_back(x);
            a.insert(x);
            a.check();
        }
        a.print();
        printf("--------------------------\n");
        for(int i=0,x;i<n;i++) {
            //scanf("%d",&x);
            RBTreeNode *tmp = a.find(arr[i]);
            printf("erase:%d\n",arr[i]);
            a.erase(tmp);
            //a.print();
            a.check();
        }
        break;
    }
    return 0;
}

 详细讲解:

红黑树 - wiki

 

posted @ 2017-11-12 19:03  cdongyang  阅读(189)  评论(0编辑  收藏  举报