红黑树 RBT

/*
红黑树(颜色平衡)  时间复杂度为 log2n  向下取整
    红黑树的性质
        1:每一个节点的颜色必须是红色或者是黑色的
        2:根节点必须是黑色的
        3:没有两个红色的孩子为父子关系
        4:终端节点可以认为是黑色的(黑哨兵)
        5:从树中的任意的节点出发到达所有可以到到达的终端节点的所有路径上的黑界点的数目必须是相同的
    根据上面的性质决定任意一条路径的长度都不可能是其他路径长度的2倍
相关的原理
    1:添加节点
        1: root为空疏 节点直接放入 作为树根
        2: 父亲节点是黑色的  直接添加节点
        3:父亲是红色的
            3_1:叔叔是红色的 父亲和叔叔都变黑 爷爷变红
                 爷为新的节点 向上调整;
                 如果爷是根节点  根节点变色 结束
                 爷节点不是根节点  继续向上层调整
            3_2:叔叔是黑色的
                3_2_1:父亲是爷爷的左孩子
                    3_2_1_1:新加入的接点是父节点的右孩子  父亲节点为节点左旋 继续向上调整
                    3_2_1_2:新加入的接点是父节点的左孩子  父亲节点变黑 爷节点变红 爷节点作为节点右旋  结束
                3_2_1:父亲是爷爷的左孩子
                    3_2_2_1:新加入的节点是父节点的左孩子  将父节点作为节点  右旋
                    3_2_2_2:新加入的节点是父节点的右孩子  父变黑 爷变红 爷节点作为节点左旋  结束
    2:删除节点
        1:当删除的节点含有两个孩子的时候 摘到左边子树的最右侧节点  
        2:需要删除的节点是根节点
            2_1:当此时的根节点没有孩子的时候  直接删除根节点  清空树    结束
            2_1:当此时的根节点含有一个孩子时  将孩子节点作为新的根节点(此事的孩子节点的颜色一定是红色的,根据RbT的性质能够推导)将新的根节点的颜色变黑  结束
        3:需要删除的节点是红色的  直接删除   结束
        4:需要删除的节点是黑色的
            4_1:需要删除的节点含有一个孩子 此时将需要删除的父亲节点与孩子节点直接链接  孩子节点变黑  结束
            4_2:需要删除的节点没有孩子
                4_2_1:当兄节点是红色的(此时的父节点一定是红色的,根据RBT的性质能够推导)
                    父节点变红  兄节点变黑
                    4_2_1_1:如果兄弟节点是父节点的右孩子
                        将父节点作为支点 左旋  更新兄节点 继续
                    4_2_1_2:如果兄弟节点是父节点的左孩子
                        将父节点作为支点 右旋  更新兄节点 继续
                4_2_2:当兄节点是黑色的
                    4_2_2_1:当两个侄子全黑  或两个侄子全是空
                        4_2_2_1_1:当父节点是红色的:
                            父节点变黑  兄弟节点变红  结束
                        4_2_2_1_2:当父节点是黑色的:
                            兄弟变红  将父节点作为新的节点  向上调整  继续
                    4_2_2_2:当左侄子是红色的  右侄子是黑色的
                        4_2_2_2_1:兄弟节点是父亲节点的左孩子
                            父亲的颜色给兄弟 父亲节点变黑 左侄子变黑 将父亲节点作为支点 右旋  结束
                        4_2_2_2_2:兄弟节点是父亲节点的右孩子
                            左侄子变黑 兄弟节点变红 将兄弟节点作为支点  右旋  更新兄弟 继续
                    4_2_2_3:当右侄子是红色的
                        4_2_2_3_1:兄弟节点是父亲节点的左孩子
                            父亲的颜色给兄弟 父亲节点变黑 右侄子变黑 将父亲节点作为支点 左旋  结束
                        4_2_2_3_2:兄弟节点是父亲节点的右孩子
                            右侄子变黑 兄弟节点变红 将兄弟亲节点节点作为支点  左旋  继续
    3:左旋
    4:右旋
    5:查找
    6:获取叔叔节点
*/

#include
#include
using namespace std;

enum COLOR{RED,BLACK};
typedef struct node{
    int value;
    int color;
    struct node *left,*right,*father;
}RBT;

void RightRemote(RBT* &root)    /*右旋*/
{
    RBT* pMark = root;
    RBT* pTmp = pMark->left;

    /*三个孩子关系*/
    pMark->left = pTmp->right;
    pTmp->right = pMark;
    if(pMark->father == NULL){
        root = pTmp;
    }
    else{
        if(pMark == pMark->father->left){
            pMark->father->left = pTmp;
        }
        else{
            pMark->father->right = pTmp;
        }
    }
    /*三个父亲关系*/
    if(pMark->left){
        pMark->left->father = pMark;
    }
    pTmp->father = pMark->father ;
    pMark->father = pTmp;
}

void LeftRemote(RBT* &root)   /*左旋*/
{
    RBT* pMark = root;
    RBT* pTmp = pMark->right;

    /*三个孩子关系*/
    pMark->right = pTmp->left;
    pTmp->left = pMark;
    if(pMark->father == NULL){
        root = pTmp;
    }
    else{
        if(pMark == pMark->father->left){
            pMark->father->left = pTmp;
        }
        else{
            pMark->father->right = pTmp;
        }
    }
    /*三个父亲关系*/
    if(pMark->right){
        pMark->right->father = pMark;
    }
    pTmp->father = pMark->father ;
    pMark->father = pTmp;
}

RBT* Find(RBT* root ,int value)     /*查找插入的节点父亲*/
{
    if(!root)  return NULL;
    while(root){
        if(value < root->value){
            if(root->left == NULL){
                return root;
            }
            root = root->left;
        }
        else if(value > root->value){
            if(root->right == NULL){
                return root;
            }
            root = root->right;
        }
        else{
            cout<<"error";
            return NULL;
        }
    }
}

RBT* GetUncle(RBT* root)   /*获取叔叔节点*/
{
    if(root == root->father->left){
        return root->father->right;
    }
    else{
        return root->father->left;
    }
}

RBT* Search(RBT* root,int value)     /*查找等value节点*/
{
    while(root){
        if(value == root->value){
            return root;
        }
        else if(value < root->value){
            root = root->left;
        }
        else{
            root = root->right;
        }
    }
    return NULL;
}

void AddNode(RBT* &root,int value)    /*添加节点*/
{
    //cout<     RBT* node = Find(root,value);
    RBT* insertnode = NULL;
    insertnode = new RBT;
    insertnode->value = value;
    insertnode->father = node;  insertnode->left = NULL; insertnode->right = NULL; insertnode->color = RED;
    // 1: root为空疏 节点直接放入 作为树根
    if(node == NULL){
        root = insertnode;
        root->color = BLACK;
        return ;
    }
    if(insertnode->value < node->value){
        node->left = insertnode;
    }
    else{
        node->right = insertnode;
    }
    // 2: 父亲节点是黑色的  直接添加节点
    if(node->color == BLACK){
        return ;
    }
    // 3:父亲是红色的
    RBT* uncle = NULL, *pgfather = NULL;
    while( node->color == RED){
        uncle = GetUncle(node);
        pgfather = node->father;
        //3_1:叔叔是红色的 父亲和叔叔都变黑 爷爷变红
        if(uncle && uncle->color == RED){
            node->color = BLACK; uncle->color = BLACK; pgfather->color = RED;
            //cout<value<             //  爷为新的节点 向上调整;
            insertnode = pgfather;
            node = insertnode->father;
            if(node == NULL){
                //  如果爷是根节点  根节点变色 结束
                root->color = BLACK;
                break;
            }
            // 爷节点不是根节点  继续向上层调整
            continue;
        }
        //3_2:叔叔是黑色的
        if(uncle == NULL || uncle->color == BLACK ){
            //3_2_1:父亲是爷爷的左孩子
            if(node == pgfather->left){
                //3_2_1_1:新加入的接点是父节点的右孩子
                if(insertnode == node->right){
                    cout<value<                     //一父亲节点为节点左旋
                    insertnode = node;
                    LeftRemote(node);
                    node = insertnode->father;
                    //继续向上调整
                    continue;
                }
                //3_2_1_2:新加入的接点是父节点的左孩子
                else{
                    //父节点变黑 爷节点变红 
                    cout<value<                     node->color = BLACK;  pgfather->color = RED;
                    //爷节点作为节点  右旋
                    if(pgfather->father == NULL){
                        RightRemote(root);
                    }
                    else{
                        RightRemote(pgfather);
                    }
                    //结束
                    break;
                }
            }
            //3_2_2:父亲是爷爷的右孩子
            else{
                //  如果添加的节点是父亲的右孩子  父亲变黑  也变红  将爷节点最为支点  左旋
                if(insertnode == node->right){
                    node->color = BLACK;  pgfather->color = RED;
                    if(pgfather->father == NULL){
                        LeftRemote(root);
                    }
                    else{
                        LeftRemote(pgfather);
                    }
                    break;
                }
                else{
                    insertnode = node;
                    RightRemote(insertnode);
                    node = insertnode->father;
                    continue;
                }
            }
        }
    }
}

void DelNode(RBT* &root,int value)
{
    if(root == NULL)  return ;
    //  查找需要删除的节点
    RBT* delnode = NULL;
    delnode = Search(root,value);
    //  当需要删除的节点是空的时候  结束操作
    if(!delnode)   return ;
    //    1:处理两个孩子的情况
    RBT* pMark = NULL;
    if(delnode->left && delnode->right){
        //  值替换  做子树的最右侧节点
        pMark = delnode;
        delnode = delnode->left;
        while(delnode->right){
            delnode = delnode->right;
        }
        //  替换值
         pMark->value = delnode->value ;
    }
    //  2:处理需要删除的节点是根节点的情况
    if(!delnode->father){  // 父亲节点为空  一定是根节点
        //  2_1:如果当前的根节点没有左右孩子  直接删除根节点  结束
        if(delnode->left == NULL && delnode->right == NULL){
            delete delnode ;
            delnode = NULL;
            root = NULL;
            return ;
        }
        //  2_2:有一个孩子 根据红黑树的性质 一定能够确定当前的孩子是红孩子
                    //此事删除根节点  将孩子节点作为心得的根节点 变为黑色
        if(delnode->left || delnode->right ){
            if(delnode->left){
                root = delnode->left;
                delnode->left = NULL;    
            }
            else{
                root = delnode->right;
                delnode->right = NULL;   
            }
            root->father = NULL;   root->color = BLACK;
            delete delnode;
            delnode = NULL;
            return ;
        }
    }
    //  3:需要删除的节点是红的  直接删除
    if(delnode->color == RED){
        if(delnode == delnode->father->left){
            delnode->father->left = NULL;
        }
        else{
            delnode->father->right = NULL;
        }
        delete delnode ;
        delnode = NULL;
        return ;
    }
    //  4:需要删除的节点是黑色的
    if(delnode->color == BLACK){
        //  4_1:有一个孩子   将需要删除节点的父节点与删除节点的孩子节点链接
        if(delnode->left || delnode->right ){
            if(delnode == delnode->father->left){
                if(delnode->left){
                    delnode->father->left = delnode->left;
                    delnode->left->color = BLACK;
                    delnode->left->father = delnode->father;
                }
                else{
                    delnode->father->left = delnode->right;
                    delnode->right->color = BLACK;
                    delnode->right->father = delnode->father;
                }
            }
            else{
                if(delnode->left){
                    delnode->father->right = delnode->left;
                    delnode->left->color = BLACK;
                    delnode->left->father = delnode->father;
                }
                else{
                    delnode->father->right = delnode->right;
                    delnode->right->color = BLACK;
                    delnode->right->father = delnode->father;
                }
            }
            delete delnode;
            delnode = NULL;
            return ;
        }
        //  4_2:删除的节点是黑色的 并且没有孩子
        RBT* brother = NULL;
        RBT* father = NULL;
        father = delnode->father;
        brother = GetUncle(delnode);

        pMark = delnode;
        //  假删除
        if(delnode = father->left){
            father->left = NULL;
        }
        else{
            father->right = NULL;
        }

        while(1){
            //  4_2_1:兄弟是红色的
            if(brother && brother->color == RED){
                //  兄弟变黑色  父亲变红
                brother->color = BLACK;   father->color = RED;
                //  4_2_1_1:兄弟是父亲节点的右孩子   将父亲节点作为支点  左旋
                if(brother == father->right){
                    LeftRemote(father);
                    brother = father->right;
                    continue;
                }
                else{
                    RightRemote(father);
                    brother = father->left;
                    continue;
                }
            }
            //  4_2_2:兄弟是黑色的
            if(brother && brother->color == BLACK){
                //  4_2_2_1:两个侄子全是黑色的
                if((brother->left == NULL && brother->right == NULL) || 
                    (brother->left != NULL && brother->left->color == BLACK && brother->right != NULL && brother->right->color == BLACK)){
                    //  4_2_2_1_1:父亲是红色的
                    if(father->color == RED){
                        //  父亲变黑  兄弟变红  结束
                        father->color = BLACK;   brother->color = RED;   
                        break;
                    }
                    else{
                        brother->color = RED;
                        delnode = father;
                        father = delnode->father;
                        brother = GetUncle(delnode);
                        continue;
                    }
                }
                //  4_2_2_2:左侄子红色  右侄子黑丝
                if((brother->left && brother->left->color == RED) && (brother->right == NULL || brother->right->color == BLACK)){
                    //  4_2_2_2_1 兄弟是父亲的右孩子
                    if(brother == father->right){
                        //  左侄子变黑   兄弟变红  将兄弟节点作为支点右旋 更新兄弟  继续
                        brother->left->color = BLACK;
                        brother->color = RED;
                        RightRemote(brother);
                        brother = father->right;
                        continue;
                    }
                    //  4_2_2_2_1 兄弟是父亲的左孩子
                    if(brother == father->left){
                        // 父为想兄色  父变黑  左侄子变黑  父亲节点作为支点右旋  结束
                        brother->color = father->color;
                        father->color = BLACK;
                        brother->left->color = BLACK;
                        RightRemote(father);
                        break;
                    }
                }
                //  4_2_2_3:右侄子是红色的
                if( brother->right && brother->right->color == RED){
                    //  4_2_2_3_1:兄弟是父亲的右孩子
                    if(brother == father->right){
                        //  右侄子变黑 父亲的颜色给兄弟  父亲变黑   将父亲节点作为支点左旋
                        brother->right->color = BLACK;
                        brother->color = father->color;
                        father->color = BLACK;
                        LeftRemote(father);
                        break;

                    }
                    //  4_2_2_3_2:兄弟是父亲的左孩子
                    if(brother == father->left){
                        //  右侄子变黑  兄弟变红  兄弟节点左为支点左旋  更换兄弟 继续
                        brother->right->color = BLACK;
                        brother->color = RED;
                        LeftRemote(brother);
                        brother = father->left;
                        continue;
                    }
                }
            }
        }
        delete delnode;
        delnode = NULL;
    }
}

void Traver_x(RBT* root)  /*先序遍历*/
{
    if(root == NULL)  return ;
    cout<value<<" ";
    Traver_x(root->left);
    Traver_x(root->right);
}

void Traver_z(RBT* root)   /*中序遍历*/
{
    if(root == NULL)  return ;
    Traver_z(root->left);
    cout<value<<" ";
    Traver_z(root->right);
}

void Traver_h(RBT* root)   /*后序遍历*/
{
    if(root == NULL)  return ;
    Traver_h(root->left);
    Traver_h(root->right);
    cout<value<<" ";
}

void f_Traver_h(RBT* root)
{
    if(root == NULL)  return ;
    stack stack_rbt;
    int tag ;
    RBT* node = NULL;
    do{
        while(root){
            stack_rbt.push(root);
            root = root->left;
        }
        tag = 1 ; node = NULL;
        while(!stack_rbt.empty() && tag){
            root = stack_rbt.top();
            if(root->right == node){
                cout<value<<" ";
                stack_rbt.pop();
                node = root;
            }
            else{
                root = root->right;
                tag = 0;
            }
        }
    }while(!stack_rbt.empty());
}

int main()
{
    int arr[] = {11,2,14,1,7,15,5,8};
    RBT* root = NULL;
    for(int i =0 ;i         AddNode(root,arr[i]);
    }
    Traver_x(root);
    cout<     Traver_z(root);
    cout<     Traver_h(root);
    cout<     f_Traver_h(root);
    cout<     AddNode(root,4);   //  添加节点
    Traver_x(root);
    cout<     
    DelNode(root,4);   //  删除节点
    Traver_x(root);
    cout<     Traver_z(root);
    cout<     Traver_h(root);
    cout<     f_Traver_h(root);
    cout<     
    system("pause");
    return 0;
}

你可能感兴趣的:(二叉树)