平衡二叉樹(AVL樹)建立、查詢、插入操作 《大話資料結構》 c++實現程式碼
阿新 • • 發佈:2019-01-05
//平衡二叉樹,或者稱為AVL樹 #include<iostream> using namespace std; typedef int status; #define true 1 #define false 0 #define LH +1 //左高 #define EH 0 //等高 #define RH -1 //右高 //二叉連結串列結點結構定義 typedef struct Bitnode { int data; int bf; //儲存結點的平衡因子 struct Bitnode *left,*right; }Bitnode,*Bitree; //操作 void R_rotate(Bitree *p); void L_rotate(Bitree *p); void Leftbalance(Bitree *T); void Rightbalance(Bitree *T); status Insertavl(Bitree *T,int e,status *taller); void Createavl(Bitree *T,int a[],int n); void Showbst(Bitree T); //中序遍歷輸出二叉樹 //f指向T的雙親,當T指向根節點時,因此f的初始呼叫值為Null //查詢成功,指標p指向該資料元素的結點,返回TRUE //查詢失敗,P指向查詢路徑上訪問的最後一個元素,返回false Bitree Searchavl(Bitree T,int key) { if (!T) return NULL; //搜尋到 if (key==T->data) return T; else if (key<T->data) { //在左子樹中搜索 return Searchavl(T->left,key); } else { //在右子樹中搜索 return Searchavl(T->right,key); } } //對以p為根的二叉排序樹做右旋處理。處理之後p指向新的樹根節點 //即旋轉之前的左子樹的根節點 void R_rotate(Bitree *p) { Bitree L; L=(*p)->left; (*p)->left=L->right; L->right=*p; *p=L; } //對以p為根的二叉排序樹做左旋處理。處理之後p指向新的樹根節點 //即旋轉之前的左子樹的根節點 void L_rotate(Bitree *p) { Bitree R; R=(*p)->right; (*p)->right=R->left; R->left=*p; *p=R; } //對以T為根的二叉排序樹做左旋平衡處理 //處理之後T指向新的樹根節點 void Leftbalance(Bitree *T) { Bitree L,Lr; L=(*T)->left; //L指向T的左子樹根結點 switch(L->bf) { //檢查T左子樹的平衡度,並做相應的處理 case LH: //新節點插入在T的左孩子的左子樹上,要做單右旋處理 (*T)->bf=L->bf=EH; R_rotate(T); break; case RH: //新節點插入在T的左孩子的右子樹上,要做單右旋處理 Lr=L->right; //Lr指向T的左孩子的右子樹根 switch(Lr->bf) { case LH: (*T)->bf=RH; L->bf=EH; break; case EH: (*T)->bf=L->bf=RH; break; case RH: (*T)->bf=EH; L->bf=LH; break; } Lr->bf=EH; L_rotate(&(*T)->left); R_rotate(T); } } //T 的右邊高,不平衡,使其平衡,左旋轉,左旋轉前先檢查R->bf //如果為LH,R要先進行右旋轉,使T->rchild->bf和T->bf一致 void Rightbalance(Bitree *T) { Bitree R,Rl; R = (*T)->right; Rl = R->left; switch(R->bf) { case RH: R->bf = (*T)->bf = EH; L_rotate(T); break; case LH: switch(R->bf) { case LH: R->bf = RH; (*T)->bf = EH; break; case EH: R->bf = (*T)->bf = EH; break; case RH: R->bf = EH; (*T)->bf = LH; break; } Rl->bf = EH; R_rotate(&R); L_rotate(T); break; } } //若在平衡的二叉排序樹T中不存在和e有相同關鍵字的結點,則插入一個 //資料元素為e的新節點並返回1,否則返回0 //若因插入使得二叉樹失去平衡,則做平衡旋轉,布林變數taller反映T長高與否 status Insertavl(Bitree *T,int e,status *taller) { if(!*T) { //插入新節點,樹長高,taller為true *T=(Bitree)malloc(sizeof(Bitnode)); (*T)->data=e; (*T)->left=(*T)->right=NULL; (*T)->bf=EH; *taller=true; } else { if(e==(*T)->data) { //樹中存在和e有相同關鍵字的結點將不再插入 *taller=false; return false; } if(e<(*T)->data) { //應繼續在t的左子樹中進行搜尋 if(!Insertavl(&(*T)->left,e,taller)) return false; if(*taller) { switch((*T)->bf) { case LH: Leftbalance(T); *taller=false; break; case EH: (*T)->bf=LH; *taller=true; break; case RH: (*T)->bf=EH; *taller=false; break; } } } else { if(!Insertavl(&(*T)->right,e,taller)) return false; if(*taller) { switch((*T)->bf) { case LH: (*T)->bf=EH; *taller=false; break; case EH: (*T)->bf=RH; *taller=true; break; case RH: Rightbalance(T); *taller=false; break; } } } } return true; } void Createavl(Bitree *T,int a[],int n) { int i; status taller; for(i=0;i<n;i++) { Insertavl(T,a[i],&taller); } } void Showbst(Bitree T) { if(T) { Showbst(T->left); cout<<T->data<<" "; Showbst(T->right); } } int main() { int a[]={62,88,58,47,35,73,51,99,37,93}; Bitree T=NULL; status taller=0; //建立二叉排序樹 Createavl(&T,a,10); cout<<"中序遍歷的結果為:"<<endl; Showbst(T); cout<<endl; //在二叉排序樹中插入56 Insertavl(&T,56,&taller); cout<<"中序遍歷的結果為:"<<endl; Showbst(T); cout<<endl; int b=58; //需要查詢的值 Bitree p=NULL; T=Searchavl(T,b); cout<<"查詢結果為:\n"<<"指標:"<<T<<endl <<"指標的值為:"<<T->data<<endl; system("pause"); return 0; }