AVL树C代码

来源:互联网 发布:淘宝有聊天壁纸设置吗 编辑:程序博客网 时间:2024/05/02 00:34
/*(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("\n\t递归前序遍历如下:\n\t");     PreOrderTraverse(T);     printf("\n");     printf("\n\t递归中序遍历如下:\n\t");     InOrderTraverse(T);     printf("\n");     printf("\n\t递归后序遍历如下:\n\t");     PostOrderTraverse(T);     printf("\n");     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("\n\t非递归前序遍历如下:\n\t");     CreatStack(S);     NonPreOrder(T,S);     printf("\n");     printf("\n\t非递归中序遍历如下:\n\t");     CreatStack(S);     NonInOder(T,S);     printf("\n");     printf("\n\t非递归后序遍历如下:\n\t");     CreatStack(S);     NonPostOrder(T,S);     printf("\n");     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("\n\t运行本程序需要先构造一个二叉树!\n");     printf("\n\t请输入需要插入的元素个数:");     scanf("%d",&n);     if(n==0)     {         printf("\n\t成功创建一个空二叉树!",n);         c=getchar();                    //用来吸收多余字符         c=getchar();                    //用来吸收多余字符     }     else    {         printf("\n\t请输入要插入的%d个元素:",n);         for(i=0;i<n;i++)                //连续输入n个元素         {             scanf("%d",&e);             InsertBST(T,e);             //插入元素         }         printf("\n\t成功创建该二叉树!",n);         c=getchar();                    //用来吸收多余字符         c=getchar();                    //用来吸收多余字符     }             while(1)                            //进入程序的循环     {         system("cls");                  //实现清屏处理         printf("                        ☆ 实现平衡二叉树的各种算法 ☆                         \n");         printf("                                                                               \n");         printf(" ◆◆◆◆◆◆◆◆◆◆◆◆  请从下面的操作中选择一项  ◆◆◆◆◆◆◆◆◆◆◆◆◆\n");         printf(" ◆                                                                          ◆\n");         printf(" ◆                     ◆ 1.在二叉树中插入新结点                            ◆\n");         printf(" ◆                     ◆ 2.实现递归的前序、中序、后序遍历二叉树            ◆\n");         printf(" ◆                     ◆ 3.实现非递归的前序、中序、后序遍历二叉树          ◆\n");         printf(" ◆                     ◆ 4.实现层次遍历二叉树                              ◆\n");         printf(" ◆                     ◆ 5.在二叉树中查找给定关键字                        ◆\n");         printf(" ◆                     ◆ 6.交换二叉树中各结点的左右子树                    ◆\n");         printf(" ◆                     ◆ 7.实现二叉树的深度的求值                          ◆\n");         printf(" ◆                     ◆ 8.统计二叉树中叶子结点数                          ◆\n");         printf(" ◆                     ◆ 9.在二叉树中删除某结点                            ◆\n");         printf(" ◆                     ◆ 0.退出本程序                                      ◆\n");         printf(" ◆                                                                          ◆\n");         printf(" ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n");         printf("\n\t你的选择是:");         scanf("%d",&ch);         switch(ch)                      //进入选择         {             case 1:                     //调用插入结点的函数             printf("\n\t请输入你想要插入的元素:");             scanf("%d",&e);             if(InsertBST(T,e)==OK)             printf("\n\t成功插入元素%d!\n",e);             else            printf("\n\t插入元素%d失败!\n",e);             break;             case 2:                     //调用打印各种递归遍历的函数             printf("\n\t平衡二叉树的各种递归遍历如下:\n");             AllOrderTraverse(T);             break;             case 3:                     //调用打印各种非递归遍历的函数             printf("\n\t平衡二叉树的各种非递归遍历如下:\n");             NonAllOrder(T,S);             break;             case 4:                     //调用打印层次遍历的函数             printf("\n\t平衡二叉树的层次遍历如下:\n\t");             CreatQueue(Q);              //创建队列             LevelTraverse(T,Q);             printf("\n");             break;             case 5:                     //调用关键字查找的函数             printf("\n\t请输入你想要查找的关键字:");             scanf("%d",&k);             if(PostsSearch(T,k)==OK)    //返回查找的值,成功返回1,失败则返回0             printf("\n\t成功找到关键字%d!\n",k);             else            printf("\n\t没有找到关键字%d!\n",k);             break;             case 6:                     //调用转换子树的函数             if(SwapSubtree(T)==OK)             printf("\n\t成功交换左右子树!\n");             else            printf("\n\t交换左右子树失败!\n");             break;             case 7:                     //调用求二叉树深度的函数             printf("\n\t平衡二叉树的深度是:");             printf("%d\n",TreeDepth(T));             break;             case 8:                     //调用统计树结点数的函数             printf("\n\t平衡二叉树的总结点数是:");             printf("%d\n",TotalNodeNum(T));             printf("\n\t平衡二叉树的叶子结点数是:");             printf("%d\n",LeafNodeNum(T));             break;             case 9:                     //调用删除结点的函数             printf("\n\t请输入你想要删除的元素:");             scanf("%d",&d);             if(DeleteBST(T,d)==OK)             printf("\n\t成功删除元素%d!\n",d);             else            printf("\n\t删除失败,没有找到元素%d!\n",d);             break;             case 0:                     //输入0,则推出本程序             return 0;             break;             default:                    //如果输入非法字符,则进入该分支             c=getchar();                //用来吸收多余字符             printf("\n\a\t输入错误,请重新输入!\n");             break;         }         scanf("%c",&c);                 //用来吸收多余字符         printf("\n\t按任意键继续,或按“n”退出!你的选择是:");         scanf("%c",&c);         if(c=='n')         return 0;     }     return 0; }

1 0
原创粉丝点击