演算法導論-AVL樹的C++實現

來源:互聯網
上載者:User

代碼主要來自網上流傳的一份南京大學陳氏三姐妹的大作業。

花了一些時間測試和修改,代碼基本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;}}

運行結果:


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.