• AVL树C代码


    /*
    (2) 前序、中序、后序遍历二叉树 (递归) 
    (3) 前序、中序、后序遍历的非递归算法  
    (4) 层次遍历二叉树  
    (5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0)  
    (6) 交换各结点的左右子树  
    (7) 求二叉树的深度  
    (8) 叶子结点数 
    (9) 删除某结点 
    */
            
    #include<stdio.h>                       //引用头文件stdio.h 
    #include<stdlib.h>                      //引用头文件stdlib.h 
    #include<malloc.h>                      //引用头文件malloc.h 
            
    #define MAXSIZE 100                     //用#define定义全局变量MAXSIZE的值为100 
    #define OK      1                       //用#define定义全局变量OK的值为1 
    #define ERROR   0                       //用#define定义全局变量ERROR的值为0 
            
    typedef int Status;                     //定义Status为int类型来表示函数返回值状态 
    typedef int ElemType;                   //定义ElemType为int类型来表示元素类型 
            
    typedef struct BSTNode                  //定义平衡二叉树结构体 
    { 
        ElemType        data;               //结点存储的数据 
        int             height;             //结点的高度 
        struct BSTNode  *lchild,*rchild;    //左、右孩子指针 
    }BSTNode,*BSTree; 
            
    typedef BSTree Position;                //定义Position为BSTree来表示节点树中位置 
            
    typedef struct                          //定义栈的结构体 
    { 
        BSTree          *base;              //在栈构造前和销毁后,base的值为NULL 
        BSTree          *top;               //栈顶指针 
        int             stacksize;          //当前已分配的存储空间,以元素为单位 
    }Stack; 
            
    typedef struct                          //定义队列的结构体 
    { 
        BSTree          *front;             //队头指针 
        BSTree          *rear;              //队尾指针 
        int             queuesize;          //当前已分配的存储空间,以元素为单位 
    }Queue; 
            
    Status InsertBST(BSTree &T,ElemType e); //实现树的节点的插入 
    Status PreOrderTraverse(BSTree T);      //实现树的递归前序遍历 
    Status InOrderTraverse(BSTree T);       //实现树的递归中序遍历 
    Status PostOrderTraverse(BSTree T);     //实现树的递归后序遍历 
    Status AllOrderTraverse(BSTree T);      //实现三种递归遍历的打印 
    Status NonPreOrder(BSTree T,Stack S);   //实现树的非递归前序遍历 
    Status NonInOder(BSTree T,Stack S);     //实现树的非递归中序遍历 
    Status NonPostOrder(BSTree T,Stack S);  //实现树的非递归后序遍历 
    Status NonAllOrder(BSTree T,Stack S);   //实现三种非递归遍历的打印 
    Status LevelTraverse(BSTree T,Queue Q); //实现二叉树的层次遍历 
    Status PostsSearch(BSTree T,ElemType e);//实现二叉树中给定关键字的查找 
    Status SwapSubtree(BSTree T);           //实现结点左右子树的交换 
    int    TreeDepth(BSTree T);             //实现二叉树深度的求值 
    int    TotalNodeNum(BSTree T);          //实现二叉树总结点数的求值 
    int    LeafNodeNum(BSTree T);           //实现二叉树叶子结点数的求值 
    Status DeleteBST(BSTree &T,ElemType e); //实现树的节点的删除 
    int    TreeHeight(BSTree T);            //实现树的高度的求值 
    int    Max(int a,int b);                //实现两个数中求最大值 
    Position MinElemSearch(BSTree T);       //实现最小元素的查找 
    BSTree LeftRotate(BSTree g);            //实现二叉树一次右旋转操作 
    BSTree RightRotate(BSTree g);           //实现二叉树一次左旋转操作 
    BSTree L_RRotate(BSTree g);             //实现一次先左旋转再右旋转操作 
    BSTree R_LRotate(BSTree g);             //实现一次先右旋转再左旋转操作 
    Status CreatStack(Stack &S);            //实现栈的建立 
    Status CreatQueue(Queue &Q);            //实现队列的建立 
            
    Status InsertBST(BSTree &T,ElemType e)  //实现在二叉树中插入新结点的函数 
    { 
        if(T==NULL)                         //判断是否为空树,是则建建立一个根节点给树 
        { 
            T=(BSTree)malloc(sizeof(BSTNode)); 
            if(!T)                          //判断该节点是否建立失败 
            return ERROR; 
            T->data=e; 
            T->height=0;                    //根节点时,高度为0 
            T->lchild=T->rchild=NULL; 
        } 
        else if(e<T->data)                  //如果输入的元素比节点数据小,则向左插入 
        { 
            InsertBST(T->lchild,e);         //递归调用该函数本身 
            if(TreeHeight(T->lchild)-TreeHeight(T->rchild)==2) 
            {                               //判断二叉树是否出现不平衡状态,是则进入该分支 
                if(e<T->lchild->data)       //若输入的数据比左孩子结点的数据小,则进行右旋转 
                T=LeftRotate(T); 
                else                        //否则先进行左旋转再右旋转 
                T=L_RRotate(T); 
            } 
        } 
        else if(e>T->data)                  //如果输入的元素比节点数据大,则向右插入 
        { 
            InsertBST(T->rchild,e);         //递归调用该函数本身 
            if(TreeHeight(T->rchild)-TreeHeight(T->lchild)==2) 
            {                               //判断二叉树是否出现不平衡状态,是则进入该分支 
                if(e>T->rchild->data)       //若输入的数据比右孩子结点的数据大,则进行左旋转 
                T=RightRotate(T); 
                else                        //否则先进行右旋转再左旋转 
                T=R_LRotate(T); 
            } 
        }                                   //如果输入数据与节点数据相等,不需要进行操作 
        T->height=Max(TreeHeight(T->lchild),TreeHeight(T->rchild))+1; 
        return OK;                          //最后需要记录节点高度 
    } 
            
    Status PreOrderTraverse(BSTree T)       //实现递归前序遍历函数 
    { 
        if(T!=NULL)                         //判断是否为空树 
        { 
            printf("%d ",T->data); 
            PreOrderTraverse(T->lchild); 
            PreOrderTraverse(T->rchild); 
        } 
        return OK; 
    } 
            
    Status InOrderTraverse(BSTree T)        //实现递归中序遍历函数 
    { 
        if(T!=NULL)                         //判断是否为空树 
        { 
            InOrderTraverse(T->lchild); 
            printf("%d ",T->data); 
            InOrderTraverse(T->rchild); 
        } 
        return OK; 
    } 
            
    Status PostOrderTraverse(BSTree T)      //实现递归后序遍历函数 
    { 
        if(T!=NULL)                         //判断是否为空树 
        { 
            PostOrderTraverse(T->lchild); 
            PostOrderTraverse(T->rchild); 
            printf("%d ",T->data); 
        } 
        return OK; 
    } 
            
    Status AllOrderTraverse(BSTree T)       //实现各种递归遍历打印函数 
    { 
        printf("
    	递归前序遍历如下:
    	"); 
        PreOrderTraverse(T); 
        printf("
    "); 
        printf("
    	递归中序遍历如下:
    	"); 
        InOrderTraverse(T); 
        printf("
    "); 
        printf("
    	递归后序遍历如下:
    	"); 
        PostOrderTraverse(T); 
        printf("
    "); 
        return OK; 
    } 
            
    Status NonPreOrder(BSTree T,Stack S)    //实现非递归前序遍历函数 
    { 
        while(S.base!=S.top||T!=NULL)       //判断栈和树是否为空 
        { 
            while(T!=NULL)                  //向左子树一直循环到最左的节点 
            { 
                printf("%d ",T->data);      //输出元素 
                *S.top++=T; 
                T=T->lchild; 
            } 
            T=*--S.top;                     //实现出栈 
            T=T->rchild;                    //转向右子树 
        } 
        return OK; 
    } 
            
    Status NonInOder(BSTree T,Stack S)      //实现非递归中序遍历函数 
    { 
        while(S.base!=S.top||T!=NULL)       //判断栈和树是否为空 
        { 
            while(T!=NULL)                  //向左子树一直循环到最左的节点 
            { 
                *S.top++=T; 
                T=T->lchild; 
            } 
            T=*--S.top;                     //实现出栈 
            printf("%d ",T->data);          //输出元素 
            T = T->rchild;                  //转向右子树 
        } 
        return OK; 
    } 
            
    Status NonPostOrder(BSTree T,Stack S)   //实现非递归后序遍历函数 
    { 
        BSTree temp=NULL;                   //定义临时变量,用来标记刚刚访问过的节点 
        while(S.base!=S.top||T!= NULL)      //判断栈和树是否为空 
        { 
            while(T!=NULL)                  //向左子树一直循环到最左的节点 
            { 
                *S.top++=T; 
                T=T->lchild; 
            } 
            T=*(S.top-1);                   //取栈顶节点 
            if(T->rchild==NULL||T->rchild==temp) 
            {                               //如果该节点没有右孩子或者其右孩子刚刚被访问过 
                printf("%d ",T->data);      //输出元素 
                S.top--;                    //已访问,使其出栈 
                temp=T;                     //标记为刚刚访问过 
                T=NULL;                     //若遍历完以该节点为根的子树,且栈空,则结束,否则继续 
            } 
            else
            T=T->rchild;                    //转向右子树 
        } 
        return OK; 
    } 
            
    Status NonAllOrder(BSTree T,Stack S)    //实现各种非递归遍历打印函数 
    { 
        printf("
    	非递归前序遍历如下:
    	"); 
        CreatStack(S); 
        NonPreOrder(T,S); 
        printf("
    "); 
        printf("
    	非递归中序遍历如下:
    	"); 
        CreatStack(S); 
        NonInOder(T,S); 
        printf("
    "); 
        printf("
    	非递归后序遍历如下:
    	"); 
        CreatStack(S); 
        NonPostOrder(T,S); 
        printf("
    "); 
        return OK; 
    } 
            
    Status LevelTraverse(BSTree T,Queue Q)  //实现层次遍历函数 
    { 
        if(T!=NULL) 
        { 
            *Q.rear++=T; 
            while(Q.front!=Q.rear)          //判断队列是否为空 
            { 
                if(T->lchild!=NULL)         //判断左子树是否为空 
                *Q.rear++=T->lchild;        //左子树进队 
                if(T->rchild!=NULL)         //判断右子树是否为空 
                *Q.rear++=T->rchild;        //右子树进队 
                T=*Q.front++;               //实现出队操作 
                printf("%d ",T->data); 
                T=*Q.front;                 //此时的队头元素 
            } 
        } 
        return OK; 
    } 
            
    Status PostsSearch(BSTree T,ElemType e) //实现在二叉树中查找给定关键字函数 
    { 
        if(T!=NULL)                         //判断二叉树是否为空 
        { 
            if(e==T->data)                  //判断查找值是否与节点数据相等 
            return OK; 
            else if(e<T->data) 
            return PostsSearch(T->lchild,e);//查找值小于节点数据,则进入左子树查找 
            else
            return PostsSearch(T->rchild,e);//查找值大于节点数据,则进入右子树查找 
        } 
        else
        return ERROR; 
    } 
            
    Status SwapSubtree(BSTree T)            //实现交换各结点的左右子树函数 
    { 
        BSTree temp;                        //定义临时变量 
        if(T!=NULL)                         //判断二叉树是否为空 
        { 
            temp=T->lchild; 
            T->lchild=T->rchild; 
            T->rchild=temp; 
            SwapSubtree(T->lchild); 
            SwapSubtree(T->rchild); 
        } 
        return OK; 
    } 
            
    int TreeDepth(BSTree T)                 //实现求二叉树的深度函数 
    { 
        int deep,ldeep=0,rdeep=0; 
        if(T!=NULL)                         //判断二叉树是否为空 
        { 
            ldeep=TreeDepth(T->lchild); 
            rdeep=TreeDepth(T->rchild); 
            deep=Max(ldeep,rdeep)+1; 
        } 
        else return 0; 
        return deep; 
    } 
            
    int TotalNodeNum(BSTree T)              //实现统计总的结点数函数 
    { 
        int sum=0,lsum=0,rsum=0; 
        if(T!=NULL)                         //判断二叉树是否为空 
        { 
            lsum=TotalNodeNum(T->lchild); 
            rsum=TotalNodeNum(T->rchild); 
            sum=lsum+rsum+1; 
            return sum; 
        } 
        else return 0; 
    } 
            
    int LeafNodeNum(BSTree T)               //实现统计叶子结点数函数 
    { 
        int dot=0,ldot=0,rdot=0; 
        if(T!=NULL)                         //判断二叉树是否为空 
        { 
            if(T->lchild==NULL&&T->rchild==NULL)    //判断是否只含有一个节点 
            dot=1; 
            else
            { 
                ldot=LeafNodeNum(T->lchild); 
                rdot=LeafNodeNum(T->rchild); 
                dot=ldot+rdot; 
            } 
        } 
        else return 0; 
        return dot; 
    } 
            
    Status DeleteBST(BSTree &T,ElemType e)  //实现在二叉树中删除某结点的函数 
    { 
        Position temp;                      //定义临时变量 
        if(T==NULL)                         //判断二叉树是否为空 
        return ERROR; 
        else if(e<T->data)                  //需要删除的数据比节点数据小的情况 
        return DeleteBST(T->lchild,e);      //继续调用函数本身进入左子树查找 
        else if(e>T->data)                  //需要删除的数据比节点数据大的情况 
        return DeleteBST(T->rchild,e);      //继续调用函数本身进入右子树查找 
        else                                //即需要删除的数据与节点数据相等的情况 
        { 
            if(T->lchild!=NULL&&T->rchild!=NULL) 
            {                                   //左右孩子都存在的情况 
                temp=MinElemSearch(T->rchild);  //在右子树中找到最小的节点 
                T->data=temp->data;             //用找到的最小节点的数据代替要删除的节点的数据 
                DeleteBST(T->rchild,T->data);   //删除右子树刚刚找到的最小的节点 
            } 
            else                            //有一个孩子或者没有孩子的情况 
            { 
                temp=T; 
                if(T->lchild==NULL)         //判断是否没有孩子的情况 
                T=T->rchild; 
                else if(T->rchild==NULL)    //判断是否有一个孩子的情况 
                T=T->lchild; 
                free(temp); 
            } 
            return OK; 
        } 
    } 
            
    int TreeHeight(BSTree T)                //实现求树的高度的函数 
    { 
        if(T==NULL)                         //判断二叉树是否为空 
        return -1; 
        else
        return T->height; 
    } 
            
    int Max(int a,int b)                    //实现求较大值的函数 
    { 
        return a>b?a:b;                     //三元运算符,哪个值大返回哪个 
    } 
            
    Position MinElemSearch(BSTree T)        //实现查找最小元素的函数 
    { 
        if(T==NULL)                         //判断二叉树是否为空 
        return NULL; 
        else if(T->lchild==NULL)            //判断是否为没有子树的情况 
        return T; 
        else
        return MinElemSearch(T->lchild); 
    } 
    /*
    	                             100                              85
                                     /                 右旋         /    
                                   85   120         ------ ->       60    100  
                                  /                                     /   
                                60    90                              80 90   120
                                  
                                   80
    */       
    BSTree LeftRotate(BSTree g)             //实现树的向右旋转函数 
    { 
        BSTree temp; 
        temp=g->lchild; 
        g->lchild=temp->rchild; 
        temp->rchild=g; 
        temp->height=Max(TreeHeight(temp->lchild),g->height)+1; 
        g->height=Max(TreeHeight(g->lchild),TreeHeight(g->rchild))+1; 
        return temp;                        //返回新的根节点 
    } 
    /*
                                      80                                   90  
                                     /               左旋               /    
                                   60    90          ---- ->            80    120
                                        /                             /     /
                                       85  120                        60  85 100
                                          /
                                        100     
    */        
    BSTree RightRotate(BSTree g)            //实现树的向左旋转函数 
    { 
        BSTree temp; 
        temp=g->rchild; 
        g->rchild=temp->lchild; 
        temp->lchild=g; 
        g->height=Max(TreeHeight(g->lchild),TreeHeight(g->rchild))+1; 
        temp->height=Max(TreeHeight(g->rchild),g->height)+1; 
        return temp;                        //返回新的根节点 
    } 
    /*
    	                          100                          100                        90
                                 /           左旋            /         右旋           /    
                                80  120     ------>          90  120    ------>        80   100  
                               /                           /                         /       
                              60 90                        80                        60  85    120
                                /                         / 
                               85                        60 85 
    */
    BSTree L_RRotate(BSTree g)              //实现树的向左旋转再向右旋转函数 
    { 
        g->lchild=RightRotate(g->lchild);   //先左旋转 
        return LeftRotate(g);               //再右旋转 
    } 
    /*
                             80                               80                                   85  
                            /                右 旋          /                 左 旋             /       
                           60   100          ------>        60   85            ------->          80 100
                                /                                                             /   /         
                               85  120                             100                         60  90  120
                                                                  /  
                                      90                          90  120
    */     
    BSTree R_LRotate(BSTree g)              //实现树的向右旋转再向左旋转函数 
    { 
        g->rchild=LeftRotate(g->rchild);    //先右旋转 
        return RightRotate(g);              //再左旋转 
    } 
            
    Status CreatStack(Stack &S)             //实现栈的建立函数 
    { 
        S.base=(BSTree*)malloc(MAXSIZE*sizeof(BSTree)); 
        if(!S.base)                         //判断是否建立失败 
        return ERROR; 
        S.top=S.base; 
        S.stacksize=MAXSIZE; 
        return OK; 
    } 
            
    Status CreatQueue(Queue &Q)             //实现队列的建立函数 
    { 
        Q.front=(BSTree*)malloc(MAXSIZE*sizeof(BSTree)); 
        if(!Q.front)                        //判断是否建立失败 
        return ERROR; 
        Q.rear=Q.front; 
        Q.queuesize=MAXSIZE; 
        return OK; 
    } 
            
    int main()                              //主函数 
    { 
        ElemType k,e,d; 
        int     i,n,ch; 
        char    c; 
        BSTree  T=NULL; 
        Stack   S; 
        Queue   Q; 
        printf("
    	运行本程序需要先构造一个二叉树!
    "); 
        printf("
    	请输入需要插入的元素个数:"); 
        scanf("%d",&n); 
        if(n==0) 
        { 
            printf("
    	成功创建一个空二叉树!",n); 
            c=getchar();                    //用来吸收多余字符 
            c=getchar();                    //用来吸收多余字符 
        } 
        else
        { 
            printf("
    	请输入要插入的%d个元素:",n); 
            for(i=0;i<n;i++)                //连续输入n个元素 
            { 
                scanf("%d",&e); 
                InsertBST(T,e);             //插入元素 
            } 
            printf("
    	成功创建该二叉树!",n); 
            c=getchar();                    //用来吸收多余字符 
            c=getchar();                    //用来吸收多余字符 
        } 
            
        while(1)                            //进入程序的循环 
        { 
            system("cls");                  //实现清屏处理 
            printf("                        ☆ 实现平衡二叉树的各种算法 ☆                         
    "); 
            printf("                                                                               
    "); 
            printf(" ◆◆◆◆◆◆◆◆◆◆◆◆  请从下面的操作中选择一项  ◆◆◆◆◆◆◆◆◆◆◆◆◆
    "); 
            printf(" ◆                                                                          ◆
    "); 
            printf(" ◆                     ◆ 1.在二叉树中插入新结点                            ◆
    "); 
            printf(" ◆                     ◆ 2.实现递归的前序、中序、后序遍历二叉树            ◆
    "); 
            printf(" ◆                     ◆ 3.实现非递归的前序、中序、后序遍历二叉树          ◆
    "); 
            printf(" ◆                     ◆ 4.实现层次遍历二叉树                              ◆
    "); 
            printf(" ◆                     ◆ 5.在二叉树中查找给定关键字                        ◆
    "); 
            printf(" ◆                     ◆ 6.交换二叉树中各结点的左右子树                    ◆
    "); 
            printf(" ◆                     ◆ 7.实现二叉树的深度的求值                          ◆
    "); 
            printf(" ◆                     ◆ 8.统计二叉树中叶子结点数                          ◆
    "); 
            printf(" ◆                     ◆ 9.在二叉树中删除某结点                            ◆
    "); 
            printf(" ◆                     ◆ 0.退出本程序                                      ◆
    "); 
            printf(" ◆                                                                          ◆
    "); 
            printf(" ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
    "); 
            printf("
    	你的选择是:"); 
            scanf("%d",&ch); 
            switch(ch)                      //进入选择 
            { 
                case 1:                     //调用插入结点的函数 
                printf("
    	请输入你想要插入的元素:"); 
                scanf("%d",&e); 
                if(InsertBST(T,e)==OK) 
                printf("
    	成功插入元素%d!
    ",e); 
                else
                printf("
    	插入元素%d失败!
    ",e); 
                break; 
                case 2:                     //调用打印各种递归遍历的函数 
                printf("
    	平衡二叉树的各种递归遍历如下:
    "); 
                AllOrderTraverse(T); 
                break; 
                case 3:                     //调用打印各种非递归遍历的函数 
                printf("
    	平衡二叉树的各种非递归遍历如下:
    "); 
                NonAllOrder(T,S); 
                break; 
                case 4:                     //调用打印层次遍历的函数 
                printf("
    	平衡二叉树的层次遍历如下:
    	"); 
                CreatQueue(Q);              //创建队列 
                LevelTraverse(T,Q); 
                printf("
    "); 
                break; 
                case 5:                     //调用关键字查找的函数 
                printf("
    	请输入你想要查找的关键字:"); 
                scanf("%d",&k); 
                if(PostsSearch(T,k)==OK)    //返回查找的值,成功返回1,失败则返回0 
                printf("
    	成功找到关键字%d!
    ",k); 
                else
                printf("
    	没有找到关键字%d!
    ",k); 
                break; 
                case 6:                     //调用转换子树的函数 
                if(SwapSubtree(T)==OK) 
                printf("
    	成功交换左右子树!
    "); 
                else
                printf("
    	交换左右子树失败!
    "); 
                break; 
                case 7:                     //调用求二叉树深度的函数 
                printf("
    	平衡二叉树的深度是:"); 
                printf("%d
    ",TreeDepth(T)); 
                break; 
                case 8:                     //调用统计树结点数的函数 
                printf("
    	平衡二叉树的总结点数是:"); 
                printf("%d
    ",TotalNodeNum(T)); 
                printf("
    	平衡二叉树的叶子结点数是:"); 
                printf("%d
    ",LeafNodeNum(T)); 
                break; 
                case 9:                     //调用删除结点的函数 
                printf("
    	请输入你想要删除的元素:"); 
                scanf("%d",&d); 
                if(DeleteBST(T,d)==OK) 
                printf("
    	成功删除元素%d!
    ",d); 
                else
                printf("
    	删除失败,没有找到元素%d!
    ",d); 
                break; 
                case 0:                     //输入0,则推出本程序 
                return 0; 
                break; 
                default:                    //如果输入非法字符,则进入该分支 
                c=getchar();                //用来吸收多余字符 
                printf("
    a	输入错误,请重新输入!
    "); 
                break; 
            } 
            scanf("%c",&c);                 //用来吸收多余字符 
            printf("
    	按任意键继续,或按“n”退出!你的选择是:"); 
            scanf("%c",&c); 
            if(c=='n') 
            return 0; 
        } 
        return 0; 
    }
    关注公众号 海量干货等你
  • 相关阅读:
    【postman】api开发必备神器
    【Nginx】Nginx服务器配置调优
    转:【微信公众号】微信snsapi_base静默授权与snsapi_userinfo网页授权的实现(不建议使用静默,直接用主动比较方便)
    【vue2.X+iview2.x】iView在非 template/render 模式下标签的转化
    【MySQL】MySQL悲观锁 + 事物 + for update 解决普通流量并发的问题
    【Redis】Redis事务详解,Redis事务支持回滚(不支持悲观锁)
    java 为什么有时一个类有多个构造函数
    一个普通类如何不实现一个接口的所有方法
    Groovy 安全导航(safe-navigation)操作符(?.)
    java 中的 ?: 埃尔维斯操作符
  • 原文地址:https://www.cnblogs.com/sowhat1412/p/12734453.html
Copyright © 2020-2023  润新知