红黑树创建和删除的原理与实现

一、定义

1 节点 只有红 和 黑两种颜色
2 根节点是黑色的
3 红色节点的子节点必须为黑色
4 从每个节点到叶节点的路径上的黑色节点数都相等。

二、创建红黑树

2.1 插入新节点

可以分为以下的几种情况:
1. 插入节点的父节点为黑色 –> 直接插入,无需调整。
2. 插入节点的父节点为红色,分为 叔节点是黑色(NULL也看作是黑色) 和 红色 两种情况。

  • 叔节点为黑色(或者是NULL) –> 根据内测插入和外侧插入 进行单旋转或者双旋转(和avl的旋转规则一样,旋转点是祖父节点),在把父节点变成黑色,祖父节点变成红色, 如祖父的父节点为也为红色,则继续向上调整(把祖父节点当做插入节点)。
  • 叔节点为红色 –> 将父节点和叔节点都变成黑色, 祖父节点 变成红色, 如祖父的父节点为也为红色,则继续向上调整(把祖父节点当做插入节点)。

易错点: 在左旋和右旋的时候,要把旋转点的父节点搞清楚,不然旋转完后就接不上了。

2.2 删除节点

类比二叉查找树的删除,进行以下分类:

  • 删除节点没有子节点
    1 删除节点为黑色 –> 少了一个黑色(“双黑”节点)
    2 删除节点为红色 –> 直接删除

  • 删除节点有 1 个子节点
    1 删除节点为黑色,子节点为红色 –> 子节点补上,并将子节点变成黑色
    2 删除节点为黑色,子节点为黑色 -->这种情况不存在
    3 删除节点为红色,子节点为黑色 --> 这种情况也不存在

  • 删除节点有 2 个子节点
    1 找左子树中最大的或者是右子树中最小的补上,再删除补上的点,这是就变成了上面两种情况了(有0个或1个子节点)

双黑节点的处理:

  • 兄弟节点是黑色,并有红色子节点
    1 左旋(双黑为左节点) ——(说明: 黄色A表示红黑均可,黑环B表示双黑) 当兄弟节点中远离B的子字节为红色时,采用左旋,旋转后C变成A的颜色,A->黑色,D–>黑色
    这里写图片描述
    2 右左旋(双黑为右结点) —— 当兄弟节点中靠近B的子字节为红色时,先将C右旋,再将A左旋,然后将D–> A的颜色,A–> 变成黑色。
    这里写图片描述
    3 右旋 —— 与左旋对称
    4 左右旋 —— 与右左旋对称

  • 兄弟节点是红色,要么有两个黑色节点,要么没有节点
    1 兄弟节点是红色,则父节点一定是黑色,将父节点进行左旋(双黑为左节点)或者右旋(双黑为右孩子),交换A和C的颜色,则此时B的兄弟节点就变成了黑色或者是NULL,就可以继续按其他的两种情况进行处理。
    这里写图片描述

  • 兄弟节点是黑色,没有红色子节点
    1 父节点是红色 –> 将父节点变成黑色,兄弟节点变成红色
    2 父节点是黑色 –> 将兄弟节点变红色,这时 父节点就变成了双黑,以父节点继续循环双黑处理

三、C++红黑树的实现

#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>

using namespace std;

typedef struct rb_node{
    int key;
    int color;
    struct rb_node* left;
    struct rb_node* right;
    struct rb_node* parent;
    rb_node(int key, int color = 1, 
            struct rb_node* left = NULL, struct rb_node* right = NULL,
            struct rb_node* parent = NULL):key(key),color(color){
        this->left = left;
        this->right = right;
        this->parent = parent;
    }
    void SetNodeRed(){ this->color = 1;}
    void SetNodeBlack(){ this->color = 0;}
    int GetNodeColor() const{ return this->color;}
    bool IsRed() const{ return (this == NULL) ? false : (this->color == 1);}
    bool IsBlack() const{ return (this == NULL) ? true : (this->color == 0);}
} RBnode,*PRBnode;

PRBnode LeftRotate(PRBnode newNode, PRBnode& tree)
{
#if 0
    if(newNode->parent != NULL){
    if(newNode->key < newNode->parent->key){
        newNode->parent->left = newNode->right;
    }else{
        newNode->parent->right = newNode->right;
    }
    }else{
    root = newNode->right;
    }
#endif
    PRBnode tmp = newNode->right;
    newNode->right = tmp->left;
    if(tmp->left != NULL) tmp->left->parent = newNode;
    tmp->left = newNode;
    tmp->parent = newNode->parent;
    newNode->parent = tmp;

    if(tmp->parent != NULL){
        if(tmp->key < tmp->parent->key){
        tmp->parent->left = tmp;
    }else{
        tmp->parent->right = tmp;
    }
    }else{
    //cout<<"===="<<endl;
        tree = tmp;
    }
    return tmp;
}

PRBnode RightRotate(PRBnode newNode, PRBnode& tree)
{
#if 0
    if(newnode->parent != NULL){
        if(newnode->key < newnode->parent->key){
            newnode->parent->left = newnode->left;
        }else{
            newnode->parent->right = newnode->left;
        }
    }else{
        root = newnode->left;
    }
#endif
    PRBnode tmp = newNode->left;
    newNode->left = tmp->right;
    if(tmp->right != NULL) tmp->right->parent = newNode;
    tmp->right = newNode;
    tmp->parent = newNode->parent;
    newNode->parent = tmp;
    if(tmp->parent != NULL){
        if(tmp->key < tmp->parent->key){
        tmp->parent->left = tmp;
    }else{
        tmp->parent->right = tmp;
    }
    }else{
    //cout<<"++++"<<endl;
        tree = tmp;
    }
    return tmp;
}

void RBtreeFixup(PRBnode x, PRBnode& root)
{
    if(x->parent->IsBlack()){
        return;
    }
    while(x->IsRed() && x->parent->IsRed()){
        PRBnode p = x->parent;
        PRBnode g = p->parent;
        PRBnode u = (p->key < g->key) ? g->right : g->left;
        PRBnode gp = g->parent;
        if(u->IsRed()){
            x->SetNodeRed();
            p->SetNodeBlack();
            u->SetNodeBlack();
            if(g->parent != NULL){
                g->SetNodeRed();
                if(g->parent->IsRed()){
                    x = g;
                }
            }
        } else {
            // 1. l
            if(x == p->right && p == g->right){
        x = LeftRotate(g, root);
                x->SetNodeBlack();
                x->left->SetNodeRed();
            }
            // 2. r
            else if(x == p->left && p == g->left){
        x = RightRotate(g,root);
                x->SetNodeBlack();
                x->right->SetNodeRed();
            }
            // 3. lr
            else if(x == p->right && p == g->left){
        LeftRotate(p,root);
        x = RightRotate(g,root);
                x->SetNodeBlack();
                x->right->SetNodeRed();  
            }
            // 4. rl
            else if(x == p->left && p == g->right){
        RightRotate(p,root);
        x = LeftRotate(g,root);
                x->SetNodeBlack();
                x->left->SetNodeRed();
                //p = x->parent;              
            }
        }
    }
}


PRBnode InsertNode(PRBnode root, int key)
{
        // 1. It is a null tree
        if(root == NULL){
            root = new RBnode(key,0);
            return root;
        }
        PRBnode tmp = root;
        PRBnode p = root;
        while(tmp != NULL){
            p = tmp;
            tmp = key < tmp->key ? tmp->left : tmp->right;
        }
        tmp = new RBnode(key, 1);
        tmp->parent = p;
        if(key < p->key){
                p->left = tmp;
        }else{
                p->right = tmp;
        }
        RBtreeFixup(tmp, root);
        return root;
}

void PrintTree(PRBnode root)
{
        if(root == NULL){
            return;
        }
        cout<<root->key<<"("<<root->color<<") ;";
        PrintTree(root->left);
        PrintTree(root->right);
}

void FreeNode(PRBnode& node)
{
    if(node == NULL) return;
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    delete node;
    node = NULL;
}

PRBnode FindMin(PRBnode root)
{
    if(root == NULL) return NULL;
    while(root->left) {
        root = root->left;
    }
    return root;
}

#if 0
PRBnode DoubleBlack(PRBnode root)
{
    if(root->parent == NULL){
        FreeNode(root);
        return NULL;
    }

    PRBnode tmp = root;

    while(1){
    if(root == root->parent->left){
        PRBnode u = root->parent->right;
        if(u->IsBlack()){ // u can not be null
            if(u->right->IsRed()){
                PRBnode x = LeftRotate(&(root->parent)); //??
                x->color = x->left->color;
                x->left->SetNodeBlack();
                x->right->SetNodeBlack();
            //  FreeNode(root);
                break;          
            } else if(u->left->IsRed()) {
                RightRotate(&u);
                PRBnode x = LeftRotate(&(root->parent));
                x->color = x->left->color;
                x->left->SetNodeBlack();
            //  FreeNode(root);
                break;  
            } else{
                if(root->parent->IsRed()){
                    root->parent->SetNodeBlack();
                    u->SetNodeRed();
                    break;
                }else{
                    u->SetNodeRed();
                    if(root->parent->parent != NULL){
                        root = root->parent;
                        continue;
                    }else{
                        break;
                    }
                }           
            }
        }else{ // u is red
            PRBnode x= LeftRotate(&(u->parent));
            x->color = x->left->color;
            x->left->SetNodeRed();
            continue; //
        }


    }
    if(root == root->parent->right){
        PRBnode u = root->parent->left;
        if(u->IsBlack()){ // u can not be null
            if(u->left->IsRed()){
                PRBnode x = RightRotate(&(root->parent)); //??
                x->color = x->right->color;
                x->right->SetNodeBlack();
                x->left->SetNodeBlack();
            //  FreeNode(root);
                break;          
            } else if(u->right->IsRed()) {
                LeftRotate(&u);
                PRBnode x = RightRotate(&(root->parent));
                x->color = x->right->color;
                x->right->SetNodeBlack();
            //  FreeNode(root);
                break;  
            } else{
                if(root->parent->IsRed()){
                    root->parent->SetNodeBlack();
                    u->SetNodeRed();
                    break;
                }else{
                    u->SetNodeRed();
                    if(root->parent->parent != NULL){
                        root = root->parent;
                        continue;
                    }else{
                        break;
                    }
                }           
            }
        }else{ // u is red
            PRBnode x= RightRotate(&(u->parent));
            x->color = x->right->color;
            x->right->SetNodeRed();
            continue; //
        }
    }
    } 
    FreeNode(tmp);

}

PRBnode DelNode(PRBnode root, int key)
{
    if(root == NULL) return NULL;
    if(key < root->key){
        root->left = DelNode(root->left, key);
    } else if(key > root->key){
        root->right = DelNode(root->right, key);
    } else {
        if(root->left == NULL && root->right == NULL){
            if(root->IsBlack()){
            // fix
                DoubleBlack(root);
            } else {
                //delete root;
                //root = NULL;
                FreeNode(root);
                return NULL;            
            }
        } else if(root->left != NULL && root->right == NULL){
            if(root->IsRed()) {
                cout<<"some error happen\n"<<endl;
                return NULL;
            }
            if(root->left->IsRed()){
                PRBnode tmp = root->left;
                tmp->SetNodeBlack();
                tmp->parent = root->parent;
                if(root->parent != NULL){
                    root->parent->left = tmp;
                }
                FreeNode(root);
                return tmp;
            } else {
                // no fix
                // black node has a black node is impossible

            }       
        } else if(root->left == NULL && root->right != NULL){
            if(root->IsRed()) {
                cout<<"some error happen\n"<<endl;
                return NULL;
            }
            if(root->right->IsRed()){
                PRBnode tmp = root->right;
                tmp->SetNodeBlack();
                tmp->parent = root->parent;
                if(root->parent != NULL){
                    root->parent->right = tmp;
                }
                FreeNode(root);
                return tmp;
            } else {
                // no fix;
                // black node has a black node is impossible

            }       
        }else{
            PRBnode tmp = FindMin(root->right);
            root->key = tmp->key;
            DelNode(root->right, tmp->key);     
        }   
    }
}
#endif

PRBnode FindNode(PRBnode tree, int key)
{
    if(tree == NULL) return NULL;
    PRBnode tmp = tree;
    while(key != tmp->key && tmp != NULL){
        if(key < tmp->key)
            tmp = tmp->left;
        else if(key > tmp->key)
            tmp = tmp->right;
    }

    return tmp;
}

void RebalanceDelete(PRBnode dbnode, PRBnode& tree)
{
    if(dbnode->parent == NULL){
        FreeNode(dbnode);
        return;
    }


        while(dbnode && dbnode != tree){
        PRBnode u = (dbnode == dbnode->parent->left)?dbnode->parent->right:dbnode->parent->left;
        if(u->IsBlack()){
        // u is black
            if(dbnode == dbnode->parent->left){
                if(u->right->IsRed()){
                    // ll
                    PRBnode x = LeftRotate(dbnode->parent, tree);
                    x->color = x->left->color;
                    x->left->SetNodeBlack();
                    x->right->SetNodeBlack();
                    break;
                }else if(u->left->IsRed()){
                    //rl
                    RightRotate(u, tree);
                    PRBnode x = LeftRotate(dbnode->parent, tree);
                    x->color = x->left->color;
                    x->left->SetNodeBlack();
                    break;              
                }else{
                // fix
                    u->SetNodeRed();
                    dbnode = dbnode->parent;            
                }
            }else if(dbnode == dbnode->parent->right){
                if(u->left->IsRed()){
                    //rr
                    PRBnode x = RightRotate(dbnode->parent, tree);
                    x->color = x->right->color;
                    x->left->SetNodeBlack();
                    x->right->SetNodeBlack();
                    break;
                }else if(u->right->IsRed()){
                    //lr
                    LeftRotate(u, tree);
                    PRBnode x = RightRotate(dbnode->parent, tree);
                    x->color = x->right->color;
                    x->right->SetNodeBlack();
                    break;              
                }else{
                // fix
                    u->SetNodeRed();
                    dbnode = dbnode->parent;            
                }
            }           
        }else{
        // u is red
            if(dbnode == dbnode->parent->left){
            // ll
                LeftRotate(dbnode->parent, tree);   
            }else if(dbnode == dbnode->parent->right){
            //rr
                RightRotate(dbnode->parent, tree);
            }
        }
    }

}





void DelNode(PRBnode& tree, int key)
{
    cout<<"DelNode key = "<<key<<endl;
    PRBnode delNode = FindNode(tree, key);
    while(delNode != NULL){
        if(delNode->left == NULL && delNode->right == NULL){
        // has 0 child
            if(delNode->IsRed()){
                if(delNode->key < delNode->parent->key)
                    delNode->parent->left = NULL;
                else
                    delNode->parent->right = NULL;
                FreeNode(delNode);
            }else{
            // need fix
                RebalanceDelete(delNode, tree);
                if(delNode->key < delNode->parent->key)
                    delNode->parent->left = NULL;
                else
                    delNode->parent->right = NULL;
                FreeNode(delNode);
            }
        }else if(delNode->left == NULL || delNode->right == NULL){
        // has 1 child
            if(delNode->IsRed()){
                cout<<"node color is error 1\n";
                return;
            }
            PRBnode backup = (delNode->left == NULL)?delNode->right:delNode->left;
            cout<<"backup = "<<backup->key<<" delnode = "<<delNode->key<<endl;
            if(backup->IsBlack()) {
                cout<<"node color is error 2\n";
                return;
            }
            backup->SetNodeBlack();
            if(delNode->key < delNode->parent->key)
                delNode->parent->left = backup;
            else
                delNode->parent->right = backup;
            backup->parent = delNode->parent;
            FreeNode(delNode);
            if(delNode == NULL) cout<<"delnode is null\n";
        }else{
        // has 2 childs
            PRBnode backup = FindMin(delNode->right);
            delNode->key = backup->key;
            delNode = backup;   
        }
    }
}



void PrintTreeRow(PRBnode root)
{
    if(root == NULL) return;
    deque<PRBnode> d;
    PRBnode cur = NULL;
    PRBnode last = root;
    PRBnode nlast = NULL;
    d.push_back(root);
    while(!d.empty()){ 
        cur = d.front();
        if(cur != NULL){
            cout<<cur->key<<"("<<cur->color;
            if(cur->parent == NULL) cout<<" null)\t";
            else cout<<" "<<cur->parent->key<<")\t";
        } else{
            cout<<"NULL\t";
        }

        d.pop_front();
        if(cur->left){
            d.push_back(cur->left);
            nlast = cur->left;
        }
        if(cur->right){
            d.push_back(cur->right);
            nlast = cur->right;     
        }
        if(last == cur){
            cout<<endl;
            last = nlast;
        }
    }
    cout<<"===================\n";
}




int main()
{
        int b[7] = {10,50,30,13,60,45,12};
        vector<int> a(b,b+7);
        int c[6] = {35,55,70,80,23,24};
        a.insert(a.end(),c,c+6);
#if 1
    for(int j=0; j<a.size(); j++){
            cout<<a[j]<<"; ";//<<endl;
         //   cout<<(void*)&(a[j])<<endl;
        }
    cout<<endl;
#endif
        PRBnode root = NULL;
        for(int i = 0; i < a.size(); i++){
                root = InsertNode(root,a[i]);
#if 0
        cout<<a[i]<<endl;
                PrintTree(root);
        cout<<endl;
        PrintTreeRow(root);

#endif
        }
    PrintTreeRow(root);

        PrintTree(root);
    cout<<endl;
    //PrintTreeRow(root);
    DelNode(root,45);

        PrintTree(root);
    cout<<endl;
    PrintTreeRow(root);
        return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值