算法导论-AVL树的C++实现

来源:互联网 发布:sql卸载 编辑:程序博客网 时间:2024/06/05 05:54

代码主要来自网上流传的一份南京大学陈氏三姐妹的大作业。

花了一些时间测试和修改,代码基本OK了,结构也比较清晰。

我两把刷子,裸写的话没一个礼拜真下不来。

#include <stdio.h>#include <malloc.h>#include <stdlib.h>#define EQ(a,b) ((a)==(b))#define LT(a,b) ((a)<(b))#define LQ(a,b) ((a)>(b))#define LH +1 //左高#define EH 0 //等高#define RH -1 //右高#define maxSize 20#define maxWidth 20typedef struct BSTNode{int data;int bf; //结点的平衡因子struct BSTNode *lchild,*rchild;//左、右孩子指针}BSTNode,*BSTree;void R_Rotate(BSTree &p); //对以*p为根的二叉排序树作右旋处理void L_Rotate(BSTree &p); //对以*p为根的二叉排序树作左旋处理void LeftBalance(BSTree &T); //对以指针T所指结点为根的二叉树作左平衡旋转处理void RightBalance(BSTree &T);//对以指针T所指结点为根的二叉树作右平衡旋转处理bool InsertAVL(BSTree &T,int e,bool &taller);//插入结点ebool SearchBST(BSTree &T,int key);//查找元素key是否在树T中void DispTree(BSTree T);//按中序遍历输出二叉树的元素void CreatBST(BSTree &T); //创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)void LeftBalance_div(BSTree &p,int &shorter);//删除结点时左平衡旋转处理void RightBalance_div(BSTree &p,int &shorter);//删除结点时右平衡旋转处理void Delete(BSTree q,BSTree &r,int &shorter);//删除结点int  DeleteAVL(BSTree &p,int x,int &shorter);//平衡二叉树的删除操作int main(){int input,search;bool taller=false;int shorter=0;BSTree T,T1,T2;T=(BSTree)malloc(sizeof(BSTNode));T=T1=T2=NULL;while(1){printf("1.Create Tree\t2.Search\t3.Insert\t4.DeleteNode\t5.Exit\n");printf("Choose what you want:\t");scanf("%d",&input);getchar();switch(input){case 1:CreatBST(T); break;case 2:printf("Input the value you want to search:");scanf("%d",&search); getchar();if(SearchBST(T,search)) printf("Success!\n",search);else printf("Faild!\n");break;case 3:printf("Input the value you want to insert:");scanf("%d",&search); getchar();InsertAVL(T,search,taller);DispTree(T); break;case 4:printf("Input the value you want to delete:");scanf("%d",&search); getchar();DeleteAVL(T,search,shorter);DispTree(T); break;case 5:            return 1;break;default:printf("Error,input again!");break;}printf("To be continue..."); getchar();}return 1;}//对以*p为根的二叉排序树作右旋处理,LL型平衡旋转法void R_Rotate(BSTree &p){BSTree lc;lc = p->lchild; //lc指向的*p左子树根结点p->lchild = lc->rchild; //lc的右子树挂接为*p的左子树lc->rchild = p;p = lc; //p指向新的结点}//对以*p为根的二叉排序树作左旋处理,RR型平衡旋转法void L_Rotate(BSTree &p){BSTree rc;rc = p->rchild; //rc指向的*p右子树根结点p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树rc->lchild = p;p = rc; //p指向新的结点}//对以指针T所指结点为根的二叉树作左平衡旋转处理,LR型平衡旋转法void LeftBalance(BSTree &T){BSTree lc,rd;lc = T->lchild; //lc指向*T的左子树根结点switch(lc->bf) //检查*T的左子树的平衡度,并作相应平衡处理{case LH: //新结点插入在*T的左孩子的左子树上,要作单右旋处理T->bf = lc->bf = EH;R_Rotate(T); break;case RH: //新结点插入在*T的左孩子的右子树上,要作双旋处理rd = lc->rchild; //rd指向*T的左孩子的右子树根switch(rd->bf) //修改*T及其左孩子的平衡因子{case LH:T->bf = RH; lc->bf = EH; break;case EH:T->bf = lc->bf = EH; break;case RH:T->bf = EH; lc->bf = LH; break;}rd->bf = EH;L_Rotate(T->lchild); //对*T的左子树作左旋平衡处理R_Rotate(T); //对*T作右旋平衡处理}}//对以指针T所指结点为根的二叉树作右平衡旋转处理,RL型平衡旋转法void RightBalance(BSTree &T){BSTree rc,ld;rc = T->rchild; //rc指向*T的右子树根结点switch(rc->bf) //检查*T的右子树的平衡度,并作相应平衡处理{case RH: //新结点插入在*T的右孩子的右子树上,要作单左旋处理T->bf = rc->bf =EH;L_Rotate(T); break;case LH: //新结点插入在*T的右孩子的左子树上,要作双旋处理ld = rc->lchild; //ld指向*T的右孩子的左子树根switch(ld->bf) //修改*T及其右孩子的平衡因子{case LH: T->bf = EH; rc->bf = RH; break;case EH: T->bf = rc->bf =EH; break;case RH: T->bf = LH; rc->bf = EH; break;}ld->bf = EH;R_Rotate(T->rchild);//对*T的右子树作左旋平衡处理L_Rotate(T); //对*T作左旋平衡处理}}//插入结点e,若T中不存在和e相同关键字的结点,则插入一个数据元素为e的新结点,并返回1,否则返回0bool InsertAVL(BSTree &T,int e,bool &taller){if(!T)//插入新结点,树"长高",置taller为true{T = (BSTree)malloc(sizeof(BSTNode));T->data = e;T->lchild = T->rchild =NULL;T->bf = EH; taller = true;}else{if(EQ(e,T->data)) //树中已存在和有相同关键字的结点则不再插入{taller = false;printf("The node have already exist!\n");return 0;}if(LT(e,T->data)) //应继续在*T的左子树中进行搜索{if(!InsertAVL(T->lchild,e,taller))return 0;//未插入if(taller) //已插入到*T的左子树中且左子树"长高"{switch(T->bf) //检查*T的平衡度{                case LH: //原本左子树比右子树高,需要作左平衡处理                LeftBalance(T);taller = false; break;                case EH: //原本左子树、右子等高,现因左子树增高而使树增高                T->bf = LH;taller = true; break;                case RH: //原本右子树比左子树高,现左、右子树等高                T->bf = EH;taller = false; break;}}}else //应继续在*T的右子树中进行搜索{if(!InsertAVL(T->rchild,e,taller))return 0;//未插入if(taller) //已插入到*T的右子树中且右子树"长高"{switch(T->bf) //检查*T的平衡度{case LH: //原本左子树比右子树高,现左、右子树等高T->bf = EH; taller = false; break;case EH: //原本左子树、右子等高,现因右子树增高而使树增高T->bf = RH; taller = true; break;case RH: //原本右子树比左子树高,需要作右平衡处理RightBalance(T); taller = false; break;}}}}return 1;}//InsertAVL//查找元素key是否在树T中bool SearchBST(BSTree &T,int key){if(!T) return false;else if(EQ(key,T->data)) return true;else if(LT(key,T->data)) return SearchBST(T->lchild,key);else return SearchBST(T->rchild,key);}//层次法打印树void DispTree(BSTree BT){    BSTree stack[maxSize],p;    int level[maxSize][2],top,n,i,width=4;    if(BT!=NULL)    {        printf("Display a tree by hollow means.\n");        top=1;        stack[top]=BT;//push root point to stack.        level[top][0]=width;        while(top>0)        {            p=stack[top];            n=level[top][0];            for(i=1;i<=n;i++)                printf(" ");            printf("%d",p->data);            for(i=n+1;i<maxWidth;i+=2)                printf("--");            printf("\n");            top--;            if(p->rchild!=NULL)            {                top++;                stack[top]=p->rchild;                level[top][0]=n+width;                level[top][1]=2;            }            if(p->lchild!=NULL)            {                top++;                stack[top]=p->lchild;                level[top][0]=n+width;                level[top][1]=1;            }        }    }}//创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)void CreatBST(BSTree &T){int e;bool taller=false;T = NULL;printf("\nPlease input a key-value(end up with -1):");scanf("%d",&e);getchar();while(e != -1){InsertAVL(T,e,taller);printf("\nPlease input a key-value(end up with -1):");scanf("%d",&e);getchar();taller=false;}if(T) DispTree(T);else printf("Empty tree.\n");}//删除结点时左平衡旋转处理void LeftBalance_div(BSTree &p,int &shorter){BSTree p1,p2;if(p->bf==1) //p结点的左子树高,删除结点后p的bf减1,树变矮{p->bf=0; shorter=1;}else if(p->bf==0)//p结点左、右子树等高,删除结点后p的bf减1,树高不变{p->bf=-1; shorter=0;}else //p结点的右子树高{p1=p->rchild;//p1指向p的右子树if(p1->bf==0)//p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变{L_Rotate(p);p1->bf=1;p->bf=-1;shorter=0;}else if(p1->bf==-1)//p1的右子树高,左旋处理后,树变矮{L_Rotate(p);p1->bf=p->bf=0; shorter=1;}else //p1的左子树高,进行双旋处理(先右旋后左旋),树变矮{p2=p1->lchild;p1->lchild=p2->rchild; p2->rchild=p1; p->rchild=p2->lchild; p2->lchild=p;if(p2->bf==0){p->bf=0; p1->bf=0;}else if(p2->bf==-1){p->bf=1;p1->bf=0;}else{p->bf=0;p1->bf=-1;}p2->bf=0;p=p2;shorter=1;}}}//删除结点时右平衡旋转处理void RightBalance_div(BSTree &p,int &shorter){BSTree p1,p2;if(p->bf==-1){p->bf=0; shorter=1;}else if(p->bf==0){p->bf=1; shorter=0;}else{p1=p->lchild;if(p1->bf==0){R_Rotate(p);p1->bf=-1; p->bf=1; shorter=0;}else if(p1->bf==1){R_Rotate(p);p1->bf=p->bf=0; shorter=1;}else{p2=p1->rchild;p1->rchild=p2->lchild; p2->lchild=p1; p->lchild=p2->rchild; p2->rchild=p;if(p2->bf==0){p->bf=0;p1->bf=0;}else if(p2->bf==1){p->bf=-1;p1->bf=0;}else{p->bf=0; p1->bf=1;}p2->bf=0; p=p2; shorter=1;}}}//删除结点void Delete(BSTree q,BSTree &r,int &shorter){if(r->rchild==NULL){q->data=r->data; q=r;r=r->lchild; free(q);shorter=1;}else{Delete(q,r->rchild,shorter);if(shorter==1)RightBalance_div(r,shorter);}}//平衡二叉树的删除操作int DeleteAVL(BSTree &p,int x,int &shorter){int k;BSTree q;if(p==NULL){printf("Hava no such node !!\n");return 0;}else if(x<p->data)//在p的左子树中进行删除{k=DeleteAVL(p->lchild,x,shorter);if(shorter==1)LeftBalance_div(p,shorter);return k;}else if(x>p->data)//在p的右子树中进行删除{k=DeleteAVL(p->rchild,x,shorter);if(shorter==1)RightBalance_div(p,shorter);return k;}else{q=p;if(p->rchild==NULL) //右子树空则只需重接它的左子树{p=p->lchild;free(q);shorter=1;}else if(p->lchild==NULL)//左子树空则只需重接它的右子树{p=p->rchild;free(q);shorter=1;}else//左右子树均不空{Delete(q,q->lchild,shorter);if(shorter==1)LeftBalance_div(p,shorter);p=q;}return 1;}}


运行结果: