红黑树的增加与删除(完整源码版)

/*
项目名称:红黑树练习
实现功能:红黑树的增加和删除
完成时间:2018年4月11日
编辑者:尹浩龙
*/
#include<iostream>
#include<ctime>
using namespace std;
//红黑树节点类
template<typename T>
class TreeNode{
public:
    T NodeData;//节点的值
    bool Color;//节点的颜色
    TreeNode<T>* Letf;//左子树
    TreeNode<T>* Right;//右子树
    TreeNode<T>* TheLast;//指向父节点
    TreeNode(T& NewNodeData);
    TreeNode(T& NewNodeData, TreeNode<T>* Letf, TreeNode<T>* Right, TreeNode<T>* TheLast, bool Color);
};
template<typename T>TreeNode<T>::TreeNode(T& NewNodeData) : NodeData(NewNodeData){
    Color = true;
    Letf = Right = TheLast = NULL;
}
template<typename T>TreeNode<T>::TreeNode(T& NewNodeData, TreeNode<T>* Letf, TreeNode<T>* Right, TreeNode<T>* TheLast, bool Color) : NodeData(NewNodeData), Letf(Letf), Right(Right), TheLast(TheLast), Color(Color){
}
template<typename A, typename B>
class RedBlackTree{
public:
    RedBlackTree();//构造函数
    void AddNode(const A& Keyword, const B& Data);//增加节点
    void DelNode(const A& Keyword);//删除节点
    void operator *();
private:
    void AntiClockwise(TreeNode<pair<A, B>>* NewNode);//左旋方法
    void Clockwise(TreeNode<pair<A, B>>* NewNode);//右旋方法
    void AddRepairTree(TreeNode<pair<A, B>>* NewNode);//增加后修复树 使树恢复红黑树的特性
    void DelRepairTree(TreeNode<pair<A, B>>* delNode, TreeNode<pair<A, B>>* Current);//删除后修复树 使树恢复红黑树的特性
    void SetRed(TreeNode<pair<A, B>>* NewNode);//设置节点为红色
    void SetBlack(TreeNode<pair<A, B>>* NewNode);//设置节点为黑色
    bool IsRed(TreeNode<pair<A, B>>* NewNode);//设置节点为红色
    void ShowRoot();//显示根节点
    void ShowSize();//显示树的节点数
    void Echo();//打印树
    void PutTree(TreeNode<pair<A, B>>* NewNode);//遍历树
    void PutNode(TreeNode<pair<A, B>>* NewNode);//打印节点
    TreeNode<pair<A, B>>* Root;//根节点指针
    int TreeSize;//树的节点
    int OutLength;//树的节点
};
template<typename A, typename B>RedBlackTree<A, B>::RedBlackTree(){
    Root = NULL;
    TreeSize = 0;
    OutLength = -1;
}
template<typename A, typename B> void RedBlackTree<A, B>::AddNode(const A& Keyword, const  B& Data){
    TreeNode<pair<A, B>>* Current = Root;
    TreeNode<pair<A, B>>* Previous = NULL;
    while (Current != NULL)
    {
        Previous = Current;
        if (Keyword > Current->NodeData.first){
            Current = Current->Right;
        }
        else if (Keyword < Current->NodeData.first){
            Current = Current->Letf;
        }
        else{
            Current->NodeData.second;
            return;
        }
    }
    TreeNode<pair<A, B>>* NewNodeData = new TreeNode<pair<A, B>>(pair<A, B>(Keyword, Data));
    if (Previous == NULL){//树为空直接涂黑插入
        NewNodeData->Color = false;
        Root = NewNodeData;
    }
    else{
        NewNodeData->TheLast = Previous;
        if (Keyword > Previous->NodeData.first){
            Previous->Right = NewNodeData;
        }
        else{
            Previous->Letf = NewNodeData;
        }
        AddRepairTree(NewNodeData);
    }
    TreeSize++;
}
template<typename A, typename B> void RedBlackTree<A, B>::DelNode(const A& Keyword){
    TreeNode<pair<A, B>>* Current = Root, *Father = NULL, *Leader = NULL, *Subordinate = NULL, *Alternate = NULL;
    while (Current != NULL&&Current->NodeData.first != Keyword)
    {
        Father = Current;
        if (Keyword > Current->NodeData.first){
            Current = Current->Right;
        }
        else{
            Current = Current->Letf;
        }
    }
    if (Current == NULL){
        cout << "指定的结点没有找到,无法删除" << endl;
        return;
    }
    if (Current->Letf != NULL&&Current->Right != NULL){//有两个孩子
        Leader = Current;
        Subordinate = Current->Letf;
        while (Subordinate->Right != NULL)//找到替换的节点
        {
            Leader = Subordinate;
            Subordinate = Subordinate->Right;
        }
        TreeNode<pair<A, B>>* Replace = new TreeNode<pair<A, B>>(Subordinate->NodeData, Current->Letf, Current->Right, Current->TheLast, Current->Color);//用替换节点的值 和删除节点的颜色和关系生成新的节点
        if (Father == NULL){//说明删除的是跟节点
            Root = Replace;
        }
        else if (Father->Letf == Current){
            Father->Letf = Replace;
        }
        else if (Father->Right == Current){
            Father->Right = Replace;
        }
        //处理要删除的节点
        if (Leader == Current){//如果直接用左子树替换删除节点
            if (Subordinate->Letf != NULL){
                Alternate = Subordinate->Letf;
                Alternate->TheLast = Replace;
            }
            else{
                Alternate = NULL;
            }
            Replace->Letf = Alternate;
        }
        else{//替换节点不是删除节点的左子树
            if (Subordinate->Letf != NULL){
                Alternate = Subordinate->Letf;
                Alternate->TheLast = Leader;
            }
            else{
                Alternate = NULL;
            }
            Leader->Right = Alternate;
        }
        DelRepairTree(Subordinate, Alternate);
        delete Subordinate;
        delete Current;
        Father = Current = Leader = Subordinate = NULL;
    }
    else{//如果有一个子树或者没有子树的情况
        if (Father == NULL){//说明删除的是跟节点 且只有一个子节点或者没有子节点
            if (Current->Letf != NULL){
                Alternate = Current->Letf;
                Alternate->TheLast = NULL;//根节点的上级指向空
            }
            else{
                Alternate = Current->Right;
                if (Alternate != NULL){
                    Alternate->TheLast = NULL;
                }
            }
            Root = Alternate;
        }
        else{//删除的不是根节点 且只有一个子节点或者没有子节点
            if (Current->Letf != NULL){//有一个左子树
                Alternate = Current->Letf;
                if (Current == Father->Letf){
                    Father->Letf = Alternate;
                }
                else{
                    Father->Right = Alternate;
                }
                Alternate->TheLast = Father;//让新连接上的节点指向正确的上级
            }
            else if (Current->Right != NULL){//有一个右子树
                Alternate = Current->Right;
                if (Current == Father->Letf){
                    Father->Letf = Alternate;
                }
                else{
                    Father->Right = Alternate;
                }
                Alternate->TheLast = Father;//让新连接上的节点指向正确的上级
            }
            else{//没有子树
                if (Current == Father->Letf){
                    Father->Letf = NULL;
                }
                else{
                    Father->Right = NULL;
                }
                Alternate = NULL;
            }
            DelRepairTree(Current, Alternate);
        }
        delete Current;
        Father = Current = NULL;
    }
    TreeSize--;
}
template<typename A, typename B> void RedBlackTree<A, B>::operator *(){
    OutLength = -1;
    cout << endl;
    ShowSize();
    ShowRoot();
    Echo();
}
template<typename A, typename B> void RedBlackTree<A, B>::AntiClockwise(TreeNode<pair<A, B>>* NewNode){//左旋
    /*
     A  <-传进来为A     转换后:             C
    / \                                  / \
    B   C                               A   E
   / \                                 / \
  D   E                             B   D
    */
    if (NewNode != NULL) {
        TreeNode<pair<A, B>>* Temp = NewNode->Right;//用一个指针指向C
        //修改子树所属
        NewNode->Right = Temp->Letf;//把C的左子树变成A的右子树
        if (Temp->Letf != NULL){//如果D为空,A的右子树为空,不需要再让D连接A,如果D不为空就把D的向上指针指向A
            Temp->Letf->TheLast = NewNode;
        }
        //修改外联节点
        Temp->TheLast = NewNode->TheLast;//C的【向上指针】指向A的【向上指针】指向,为C替代A做准备
        if (NewNode->TheLast == NULL){//如果A的【向上指针】等于空说明A是红黑树的根节点
            Root = Temp;//当A是根节点时需要把根节点移动到C 让C成为新的根节点
        }
        else if (NewNode->TheLast->Letf == NewNode)//A节点是上级节点的左子树就让C成为A上级的左子树
            NewNode->TheLast->Letf = Temp;
        else
            NewNode->TheLast->Right = Temp;
        Temp->Letf = NewNode;//让A成为C的左子树
        NewNode->TheLast = Temp;//连接A到C
    }
}
template<typename A, typename B> void RedBlackTree<A, B>::Clockwise(TreeNode<pair<A, B>>* NewNode){//右旋
    /*
        A    <-传递进来A     转换后:              B
       / \                                     / \
      B   C                                   D   A
     / \                                         / \
    D   E                                       E   C
    */
    if (NewNode != NULL) {
        TreeNode<pair<A, B>>* Temp = NewNode->Letf;//用一个指针指向B
        //修改子树所属
        if (Temp->Right != NULL){//如果E为空,A的左子树为空,不需要再让E连接A,如果E不为空就把E的向上指针指向A
            NewNode->Letf = Temp->Right;//把C的左子树变成A的右子树
            Temp->Right->TheLast = NewNode;
        }
        else{
            NewNode->Letf = NULL;
        }
        //修改外联节点
        Temp->TheLast = NewNode->TheLast;//B的【向上指针】指向A的【向上指针】指向,为B替代A做准备
        if (NewNode->TheLast == NULL){//如果A的【向上指针】等于空说明A是红黑树的根节点
            Root = Temp;//当A是根节点时需要把根节点移动到C 让C成为新的根节点
            Temp->Color = false;
        }
        else if (NewNode->TheLast->Letf == NewNode)//A节点是上级节点的左子树就让C成为A上级的左子树
            NewNode->TheLast->Letf = Temp;
        else
            NewNode->TheLast->Right = Temp;
        Temp->Right = NewNode;//让A成为C的右子树
        NewNode->TheLast = Temp;//连接A到C
    }
}
template<typename A, typename B> void RedBlackTree<A, B>::AddRepairTree(TreeNode<pair<A, B>>* NewNode){
    TreeNode<pair<A, B>>*Grandpa = NULL, *Pedar = NULL, *Uncle = NULL, *Temp = NULL;
    while (NewNode->TheLast != NULL&&NewNode->TheLast->Color)//如果NewNNewNode->TheLast==NULL说明到达根节点或者父节点不是红色不用继续处理
    {
        Pedar = NewNode->TheLast;
        Grandpa = Pedar->TheLast;
        if (Pedar == Grandpa->Letf){//说明父亲在爷爷的左侧
            Uncle = Grandpa->Right;//找到叔叔节点
            if (Uncle != NULL&& Uncle->Color){//如果叔叔是红色
                SetBlack(Uncle);//把叔叔和父亲都改为黑色 爷爷改为红色
                SetBlack(Pedar);
                SetRed(Grandpa);
                NewNode = Grandpa;
                continue;
            }
            else{
                if (NewNode == Pedar->Right){
                    //如果新节点在父亲右侧  父亲在爷爷左侧 就旋转为左侧处理  
                    //此处判断不能写成赋值 写成赋值后程序不会报错 根节点不会变化 红黑树就不成立了  
                    AntiClockwise(Pedar);
                    NewNode = Pedar;
                    continue;
                }
                SetBlack(Pedar);
                SetRed(Grandpa);
                Clockwise(Grandpa);
                NewNode = Pedar;
            }
        }
        else{//父亲在爷爷的右侧
            Uncle = Grandpa->Letf;//找到叔叔节点
            if (Uncle != NULL&& Uncle->Color){//如果叔叔是红色
                SetBlack(Uncle);//把叔叔和父亲都改为黑色 爷爷改为红色
                SetBlack(Pedar);
                SetRed(Grandpa);
                NewNode = Grandpa;
                continue;
            }
            else{
                if (NewNode == Pedar->Letf){
                    Clockwise(Pedar);
                    NewNode = Pedar;
                    continue;
                }
                SetBlack(Pedar);
                SetRed(Grandpa);
                AntiClockwise(Grandpa);
                NewNode = Pedar;
            }
        }

    }
    SetBlack(Root);
}
template<typename A, typename B> void RedBlackTree<A, B>::DelRepairTree(TreeNode<pair<A, B>>* delNode, TreeNode<pair<A, B>>* Current){
    TreeNode<pair<A, B>>* Pedar = NULL, *Brother = NULL;
    if (!IsRed(delNode)){
        Pedar = delNode->TheLast;
        while (Current != Root && (Current == NULL || !IsRed(Current))){
            if (Current == Pedar->Letf) {
                Brother = Pedar->Right;
                if (Brother != NULL&&IsRed(Brother)){
                    SetBlack(Brother);
                    SetRed(Pedar);
                    AntiClockwise(Pedar);
                    Brother = Pedar->Right;
                }
                if ((Brother->Letf == NULL || !IsRed(Brother->Letf)) && (Brother->Right == NULL || !IsRed(Brother->Right))){
                    //兄弟节点没有子树 或者子树都为黑的情况
                    SetRed(Brother);
                    Current = Pedar;
                    Pedar = Pedar->TheLast;
                }
                else{
                    if (Brother->Right == NULL || !IsRed(Brother->Right)){
                        if (Brother->Letf != NULL)SetBlack(Brother->Letf);
                        SetRed(Brother);
                        Clockwise(Brother);
                        Brother = Pedar->Right;
                    }
                    Brother->Color = Pedar->Color;
                    SetBlack(Current);
                    if (Brother->Right != NULL)SetBlack(Brother->Right);
                    AntiClockwise(Pedar);
                    break;
                }
            }
            else {                  // same as above, with _M_right <-> _M_left.  
                Brother = Current->Letf;
                if (IsRed(Brother)) {
                    SetBlack(Brother);
                    SetRed(Pedar);
                    Clockwise(Pedar);
                    Brother = Pedar->Letf;
                }
                if ((Brother->Right == NULL || !IsRed(Brother->Right)) && (Brother->Letf == NULL || !IsRed(Brother->Letf))){
                    SetRed(Brother);
                    Current = Pedar;
                    Pedar = Pedar->TheLast;
                }
                else {
                    if (Brother->Letf == NULL || !IsRed(Brother->Letf)){
                        if (Brother->Right != NULL)SetBlack(Brother->Right);
                        SetRed(Brother);
                        AntiClockwise(Brother);
                        Brother = Pedar->Letf;
                    }
                    Brother->Color = Pedar->Color;
                    SetBlack(Pedar);
                    if (Brother->Letf != NULL)SetBlack(Brother->Letf);
                    Clockwise(Pedar);
                    break;
                }
            }
        }
        SetBlack(Current);
    }
}
template<typename A, typename B> void RedBlackTree<A, B>::SetRed(TreeNode<pair<A, B>>* NewNode){
    NewNode->Color = true;
}
template<typename A, typename B> void RedBlackTree<A, B>::SetBlack(TreeNode<pair<A, B>>* NewNode){
    NewNode->Color = false;
}
template<typename A, typename B> bool RedBlackTree<A, B>::IsRed(TreeNode<pair<A, B>>* NewNode){
    return NewNode->Color;
}
template<typename A, typename B> void RedBlackTree<A, B>::ShowRoot(){
    cout << "根节点是:"; PutNode(Root);
}
template<typename A, typename B> void RedBlackTree<A, B>::ShowSize(){
    cout << "当前树中有节点:" << TreeSize << "个。" << endl;
}
template<typename A, typename B> void RedBlackTree<A, B>::Echo(){
    cout << "红黑树节点列表:" << endl;
    PutTree(Root); cout << endl;
}
template<typename A, typename B> void RedBlackTree<A, B>::PutTree(TreeNode<pair<A, B>>* NewNode){
    if (NewNode != NULL){
        PutTree(NewNode->Letf);
        PutNode(NewNode);
        PutTree(NewNode->Right);
    }
}
template<typename A, typename B> void RedBlackTree<A, B>::PutNode(TreeNode<pair<A, B>>* NewNode){
    cout << "\t[" << NewNode->NodeData.first << "|" << NewNode->Color << "|" << NewNode->NodeData.second << "]";
    OutLength++;
    if (OutLength % 3 == 0){
        cout << endl;
    }
}
int main(){
    srand((unsigned)time(NULL));
    RedBlackTree<int, int> myTree;
    for (int i = 1; i < 27; i++)
        myTree.AddNode(i, rand() % 1000 + 1000);
    *myTree;
    myTree.DelNode(1);
    *myTree;
    myTree.DelNode(9);
    *myTree;
    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章