红黑树!

当初做课设选的红黑树已经一段时间了,查了很多资料看了很多的blog,终于弄清楚搞明白,本来想清楚明白的写个红黑树的blog,奈何文笔生涩,遂放弃,直接上代码各位凑合着看。哦对,强烈推荐一些资料,看完你就明白红黑树怎么回事以及怎么写了。
1.数据结构与算法C语言描述,看看其中关于AVL树的理解以及实现。
2.算法导论,上本书在红黑树的描述方面并不理想,看完算导关于红黑树的内容简直有种修成武林第一功法的快感。
3.一篇红黑树的论文,具体自己找吧。英文的,忘了自己在哪儿找的,貌似是大牛的论文。
以下是代码:

/* 红黑树的实现 * 红黑树是带有平衡条件(着色性质)的二叉查找树 * 1)节点要么红色要么黑色 * 2)根节点为黑色 * 3)叶节点(哨兵)必黑 * 4)若节点为红色,其子节点必黑 * 5)一个节点到一个NULL指针的路径必须包含相同的黑色节点 * 2016-12-24 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 红黑树的类型声明 */
typedef int KeyType;
typedef enum {Red , Black} ColorType;

/* 红黑树节点类型 */
typedef struct TreeNode{
    KeyType Key;
    struct TreeNode *Left;
    struct TreeNode *Right;
    struct TreeNode *Parent;
    ColorType Color;
}Node,*PNode;

/* 红黑树树类型 */
typedef struct RBTree{
    PNode Root;
    PNode Nil;    
}RBTree,*PRBTree;

/* 构造函数 */
PRBTree Intialize();
void MakeEmpty(PRBTree T);
PNode Search(KeyType k,PRBTree T);
void Insert(KeyType k,PRBTree T);
void InsertFixup(PRBTree T,PNode Z);
void DeleteWithKey(KeyType k,PRBTree T);
void DeleteFixup(PRBTree T,PNode Z);
void TransPlant(PRBTree,PNode u,PNode v);
PNode FindMin(PRBTree T,PNode t);
PNode FindMax(PRBTree T,PNode t);
void LeftRotate(PRBTree T,PNode X);
void RightRotate(PRBTree T,PNode X);
void MidOutputTree(PRBTree T,PNode x);
void PreOutputTree(PRBTree T,PNode x);
void BehOutputTree(PRBTree T,PNode x);
void menu();
char *StringColor(ColorType col);

/* 转化输出 */
char *StringColor(ColorType col){
    switch(col){
        case Red:
            return "红";
            break;
        case Black:
            return "黑";
            break;
        default:
            break;
    }
    return "错误";
}
void menu()
{
    printf("*---------------------红黑树--------------------*\n");
    printf("1---------创建红黑树 2-----------置空红黑树\n");
    printf("3---------插入节点 4-----------删除节点\n");
    printf("5---------最小节点 6-----------最大节点\n");
    printf("7---------查找节点 8-----------输出红黑树\n");
    printf("0---------帮助 e-----------退出\n");
    printf("*---------------------------------------------*\n");
}

/* 中序输出 */
void MidOutputTree(PRBTree T,PNode x){
    if(x != T -> Nil){
    MidOutputTree(T,x -> Left);
    printf("%d\t",x -> Key);
    MidOutputTree(T,x -> Right);
    }
}
void PreOutputTree(PRBTree T,PNode x){
    if(x != T->Nil){
        printf("%d\t",x->Key);
        PreOutputTree(T,x->Left);
        PreOutputTree(T,x->Right);
    }
}
void BehOutputTree(PRBTree T,PNode x){
    if(x != T->Nil){
        BehOutputTree(T,x->Left);
        BehOutputTree(T,x->Right);
        printf("%d\t",x->Key);
    }
}
/* 初始化创建红黑树 */
PRBTree Intialize(){
    PRBTree T;
    KeyType k;
    T = malloc(sizeof(RBTree));
    T -> Nil = malloc(sizeof(Node));
    T -> Root = malloc(sizeof(Node));
    T -> Nil -> Key = -1;
    T -> Nil -> Color = Black;
    T -> Nil -> Left = T -> Nil -> Right = T -> Nil -> Parent = NULL;
    T -> Root = T -> Nil;
    printf("输入节点的值(输入-1则结束):");
    scanf("%d",&k);
    while(k!=-1){
        Insert(k,T);
        scanf("%d",&k);
    }
    return T;
}

/* 按关键字查找 */
PNode Search(KeyType k,PRBTree T){
    PNode x = T -> Root;
    while(x -> Key != k && x != T -> Nil){
        if(k < x -> Key)
            x = x -> Left;
        else
            x = x -> Right;
    }
    return x;
}

/* 置空 */
void MakeEmpty(PRBTree T){
    T -> Root = T -> Nil;
}

/* 最大值非递归实现 */
PNode FindMax(PRBTree T,PNode t){
    PNode x = t;
    while(x -> Right != T -> Nil)
        x = x -> Right;
        return x;
}

/* 最小值非递归实现 */
PNode FindMin(PRBTree T,PNode t){
    PNode x = t;
    while(x -> Left != T -> Nil)
        x = x -> Left;
    return x;
}

/* 左旋 */
void LeftRotate(PRBTree T,PNode X){
    PNode Y;
    Y = X -> Right;
    X -> Right = Y -> Left;
    if(Y -> Left != T -> Nil)
        Y -> Left -> Parent = X;
    Y -> Parent = X -> Parent;
    if(X -> Parent == T -> Nil)
        T -> Root = Y;
    else if(X == X -> Parent -> Left)
        X -> Parent -> Left = Y;
    else
        X -> Parent -> Right = Y;
    Y -> Left = X;
    X -> Parent = Y;
}

/* 右旋 */
void RightRotate(PRBTree T,PNode X){
    PNode Y;
    Y = X -> Left;
    X -> Left = Y -> Right;
    if(Y -> Right != T -> Nil)
        Y -> Right -> Parent = X;
    Y -> Parent = X -> Parent;
    if(X -> Parent == T -> Nil)
        T -> Root = Y;
    else if(X == X -> Parent -> Left)
        X -> Parent -> Left = Y;
    else
        X -> Parent -> Right = Y;
    Y -> Right = X;
    X -> Parent = Y;
}

/* 插入 */
void Insert(KeyType k,PRBTree T){
    PNode X,Y,Z;
    Y = T -> Nil;
    X = T -> Root;
    Z = malloc(sizeof(Node));
    Z -> Key = k;
    while(X != T -> Nil){
        Y = X;
        if(Z -> Key < X -> Key)
            X = X -> Left;
        else if(Z -> Key > X -> Key)
            X = X -> Right;
        else{
            printf("已经存在该节点!\n");
            return;
        }
    }
    Z -> Parent = Y;
    if(Y == T -> Nil)
        T -> Root = Z;
    else if(Z -> Key < Y -> Key)
        Y -> Left = Z;
    else
        Y -> Right = Z;
    Z -> Left = Z -> Right = T -> Nil;
    Z -> Color = Red;
    InsertFixup(T,Z);
    printf("插入成功!\n");
}

/* 插入后修复红黑树性质 */
void InsertFixup(PRBTree T,PNode Z){
    PNode Y;
    while(Z -> Parent -> Color == Red){
        if(Z -> Parent == Z -> Parent -> Parent -> Left){
            Y = Z -> Parent -> Parent -> Right;
            if(Y -> Color == Red){
                Z -> Parent -> Color = Black;
                Y -> Color = Black;
                Z -> Parent -> Parent -> Color = Red;
                Z = Z -> Parent -> Parent;
            }
            else{ 
                if(Z == Z -> Parent -> Right){
                    Z = Z -> Parent;
                    LeftRotate(T,Z);
                }
                Z -> Parent -> Color = Black;
                Z -> Parent -> Parent -> Color = Red;
                RightRotate(T,Z -> Parent -> Parent);
            }
        }
        else{
            Y = Z -> Parent -> Parent -> Left;
            if(Y -> Color == Red){
                Z -> Parent -> Color = Black;
                Y -> Color = Black;
                Z -> Parent -> Parent -> Color = Red;
                Z = Z -> Parent -> Parent;
                //LeftRotate(T,Z);
            }
            else{
                if(Z == Z -> Parent -> Left){
                    Z = Z -> Parent;
                    RightRotate(T,Z);
                }
                Z -> Parent -> Color = Black;
                Z -> Parent -> Parent -> Color = Red;
                LeftRotate(T,Z -> Parent -> Parent);
            }
        }
    }
    T -> Root -> Color = Black;
}

/* 删除辅助函数,用v代替u */
void TransPlant(PRBTree T,PNode u,PNode v){
    if(u -> Parent == T -> Nil)
        T -> Root = v;
    else if(u == u -> Parent -> Left)
        u -> Parent -> Left = v;
    else
        u -> Parent -> Right = v;
    v -> Parent = u -> Parent;
}

/* 删除函数 */
void DeleteWithKey(KeyType k,PRBTree T){
    PNode x,y,z;
    ColorType y_original_color;
    z = Search(k,T);
    y = z;
    y_original_color = y -> Color;
    if(z -> Left == T -> Nil){
        x = z -> Right;
        TransPlant(T,z,z -> Right);
    }
    else if(z -> Right == T -> Nil){
        x = z -> Left;
        TransPlant(T,z,z -> Left);
    }
    else{
        y = FindMin(T,z -> Right);
        y_original_color = y -> Color;
        x = y -> Right;
        if(y -> Parent == z)
            x -> Parent = y;
        else{
            TransPlant(T,y,y -> Right);
            y -> Right = z -> Right;
            y -> Right -> Parent = y;
        }
        TransPlant(T,z,y);
        y -> Left = z -> Left;
        y -> Left -> Parent = y;
        y -> Color = z -> Color;
    }
    if(y_original_color == Black)
        DeleteFixup(T,x);
}

/* 删除修复函数保持红黑树的性质 */
void DeleteFixup(PRBTree T,PNode x){
    PNode w;
    while(x != T -> Root && x -> Color == Black){
        if(x == x -> Parent -> Left){
            w = x -> Parent -> Right;
            if(w -> Color == Red){
                w -> Color = Black;
                x -> Parent -> Color = Red;
                LeftRotate(T,x -> Parent);
                w = x -> Parent -> Right;
            }
            if(w -> Left -> Color == Black && w -> Right -> Color == Black){
                w -> Color = Red;
                x = x -> Parent;
            }
            else{ 
                if(w -> Right -> Color == Black){
                w -> Left -> Color = Black;
                w -> Color = Red;
                RightRotate(T,w);
                w = x -> Parent -> Right;
                }
                w -> Color = x -> Parent -> Color;
                x -> Parent -> Color = Black;
                w -> Right -> Color = Black;
                LeftRotate(T,x -> Parent);
                x = T -> Root;
            }
        }
        else{
            w = x -> Parent -> Left;
            if(w -> Color == Red){
                w -> Color = Black;
                x -> Parent -> Color = Red;
                RightRotate(T,x -> Parent);
                w = x -> Parent -> Left;
            }
            if(w -> Right -> Color == Black && w -> Left -> Color == Black){
                w -> Color = Red;
                x = x -> Parent;
            }
            else{
                if(w -> Left -> Color == Black){
                    w -> Right -> Color = Black;
                    w -> Color = Red;
                    LeftRotate(T,w);
                    w = x -> Parent -> Left;
                }
                w -> Color = x -> Parent -> Color;
                x -> Parent -> Color = Black;
                w -> Left -> Color = Black;
                RightRotate(T,x -> Parent);
                x = T -> Root;
            }
        }
    }
    x -> Color = Black;
}

int main()
{
    PRBTree Tree = NULL;
    KeyType key;
    PNode x;
    char ch;
    menu();
    while (1)
    {
        printf(">>");
        ch = getchar();
        switch (ch){
            case '0':
                menu();
                break;
            case '2':
                if(Tree == NULL||Tree->Root==Tree->Nil){
                    printf("空树,请先创建!\n");
                    break;
                }
                MakeEmpty(Tree);
                printf("已经置空\n");
                break;
            case '1':
                Tree = Intialize();
                break;
            case '3':
                printf("输入关键字:");
                scanf("%d", &key);
                Insert(key,Tree);
                //printf("插入成功!\n");
                break;
            case '4':
                if (Tree == NULL||Tree->Root==Tree->Nil){
                    printf("这是一颗空树无法删除!\n");
                    break;
                }
                printf("输入想要删除节点的关键字:");
                scanf("%d", &key);
                x = Search(key, Tree);
                if (x != Tree->Nil){
                    DeleteWithKey(key, Tree);
                    printf("删除成功!\n");
                }
                else 
                    printf("没有节点与此关键字匹配! \n");
                break;
            case '5':
                if (Tree == NULL || Tree->Root==Tree->Nil){
                    printf("空树,请先创建!\n");
                    break;
                }
                x = FindMin(Tree,Tree -> Root);
                if(x == Tree -> Nil)
                    printf("没有此节点\n");
                else
                    printf("最小节点为:%d\n其颜色为:%s\n",x->Key,StringColor(x->Color));
                if(x -> Parent != Tree -> Nil)
                    printf("父节点为:%d\n",x->Parent->Key);
                else
                    printf("无父节点!\n");
                if(x -> Left != Tree -> Nil)
                    printf("左孩子为:%d\n",x->Left->Key);
                else
                    printf("无左孩子!\n");
                if(x -> Right != Tree -> Nil)
                    printf("右孩子为:%d\n",x->Right->Key);
                else
                    printf("无右孩子!\n");
                break;
                break;
            case '6':
                if (Tree == NULL || Tree->Root==Tree->Nil){
                    printf("树为空请先创建!\n");
                    break;
                }
                x = FindMax(Tree, Tree->Root);
                if(x == Tree -> Nil)
                    printf("没有此节点\n");
                else
                    printf("最大节点为:%d\n其颜色为:%s\n",x->Key,StringColor(x->Color));
                if(x -> Parent != Tree -> Nil)
                    printf("父节点为:%d\n",x->Parent->Key);
                else
                    printf("无父节点!\n");
                if(x -> Left != Tree -> Nil)
                    printf("左孩子为:%d\n",x->Left->Key);
                else
                    printf("无左孩子!\n");
                if(x -> Right != Tree -> Nil)
                    printf("右孩子为:%d\n",x->Right->Key);
                else
                    printf("无右孩子!\n");
                break;
                break;
            case '7':
                if(Tree == NULL||Tree->Root==Tree->Nil){
                    printf("树为空,请先创建\n!");
                    break;
                }
                printf("输入查找节点的值:");
                scanf("%d",&key);
                x = Search(key,Tree);
                if(x == Tree -> Nil)
                    printf("没有此节点\n");
                else{
                    printf("此节点存在!\n其颜色为:%s\n",StringColor(x->Color));
                    if(x -> Parent != Tree -> Nil)
                        printf("父节点为:%d\n",x->Parent->Key);
                    else
                        printf("无父节点!\n");
                    if(x -> Left != Tree -> Nil)
                        printf("左孩子为:%d\n",x->Left->Key);
                    else
                        printf("无左孩子!\n");
                    if(x -> Right != Tree -> Nil)
                        printf("右孩子为:%d\n",x->Right->Key);
                    else
                        printf("无右孩子!\n");
                }
                break;
            case '8':
                if (Tree == NULL || Tree->Root==Tree->Nil){
                    printf("树为空,请先创建!\n");
                    break;
                }
                printf("中序:"); MidOutputTree(Tree,Tree->Root); printf("\n");
                printf("前序:"); PreOutputTree(Tree,Tree->Root); printf("\n");
                printf("后序:"); BehOutputTree(Tree,Tree->Root); printf("\n");
                break;
            case 'e':
                return 0;
            case '\n':
                break;
            default:
                menu();
                break;
        }
    }
    return 0;
}
点赞