我覺得這個是最通俗易懂的版本了,,改編自網上,,出處忘了,我完整了他的代碼,並把風格改成我的了,,函數實在不喜歡一股腦的全部扔上面,。,,,。
建議閱讀這兩篇文章:
http://www.cnblogs.com/fornever/archive/2011/11/15/2249492.html
#include<stdio.h> #include<stdlib.h> #define EH 0 /*等高*/ #define LH 1 /*左高*/ #define RH -1 /*右高*/ typedef int ElemType; /*數據類型*/ typedef struct BiTree{ ElemType data; /*數據元素*/ int BF; /*平衡因子*/ struct BiTree *lchild,*rchild; /*左右子女指針*/ }*Bitree,BitreeNode; int InsertAVL(Bitree *T,ElemType e,bool *taller); void LeftBalance(Bitree *T); void RightBalance(Bitree *T); void R_Rotate(Bitree *T); void L_Rotate(Bitree *T); bool *taller=(bool*)malloc(sizeof(bool)); int main(void) { int data; Bitree T=NULL; while(1) { printf("enter the number(zero to exit):"); scanf("%d",&data); if(0==data)break; InsertAVL(&T,data,taller); } return 0; } /*若在平衡的二叉排序樹T 中不存在和e 有相同關鍵碼的結點,則插入一個數據元素為e 的*/ /*新結點,並反回1,否則反回0。若因插入而使二叉排序樹失去平衡,則作平衡旋轉處理,*/ /*布爾型變量taller 反映T 長高與否*/ int InsertAVL(Bitree *T,ElemType e,bool *taller) { if(!*T) /*插入新結點,樹“長高”,置taller 為TURE*/ { (*T)=(Bitree)malloc(sizeof(BitreeNode)); (*T)->data = e; (*T)->lchild = (*T)->rchild = NULL; (*T)->BF = EH; *taller = true; } else { if(e==(*T)->data) /*樹中存在和e 有相同關鍵碼的結點,不插入*/ { *taller = false; return 0; } if(e<(*T)->data) { if(!InsertAVL(&(*T)->lchild,e,taller)) return 0; /*未插入*/ if(*taller) switch((*T)->BF) { case EH : /*原本左、右子樹等高,因左子樹增高使樹增高*/ (*T)->BF=LH; *taller=true; break; case LH : /*原本左子樹高,需作左平衡處理*/ LeftBalance(T); *taller=false; break; case RH : /*原本右子樹高,使左、右子樹等高*/ (*T)->BF=EH; *taller=false; break; } } else { if(!InsertAVL(&(*T)->rchild,e,taller)) return 0; /*未插入*/ if(*taller) switch((*T)->BF) { case EH : /*原本左、右子樹等高,因右子樹增高使樹增高*/ (*T)->BF=RH; *taller=true; break; case LH : /*原本左子樹高,使左、右子樹等高*/ (*T)->BF=EH; *taller=false; break; case RH : /*原本右子樹高,需作右平衡處理*/ RightBalance(T); *taller=false; break; } } } return 1; } /*對以*p 指向的結點為根的子樹,作左平衡旋轉處理,處理之后,*p 指向的結點為子樹的新根*/ void LeftBalance(Bitree *T) { Bitree L=(*T)->lchild,Lr; /*L 指向*T左子樹根結點*/ switch(L->BF) /*檢查L 平衡度,並作相應處理*/ { case LH: /*新結點插在*p 左子樹的左子樹上,需作單右旋轉處理*/ (*T)->BF=L->BF=EH; R_Rotate(T); break; case EH: /*原本左、右子樹等高,因左子樹增高使樹增高*/ (*T)->BF=LH; //這里的EH好像沒有寫的必要 *taller=true; break; case RH: /*新結點插在*T 左孩子的右子樹上,需作先左后右雙旋處理*/ Lr=L->rchild; /*Lr 指向*p 左孩子的右子樹根結點*/ switch(Lr->BF) /*修正*T 及其左子樹的平衡因子*/ { case LH: (*T)->BF = RH; L->BF = EH; break; case EH: (*T)->BF = L->BF= EH; break; case RH: (*T)->BF = EH; L->BF = LH; break; } Lr->BF = EH; L_Rotate(&L); /*對*T 的左子樹作左旋轉處理*/ R_Rotate(T); /*對*T 作右旋轉處理*/ } } //這里和leftbalance一個道理,試着自己寫一下 void RightBalance(Bitree *T) { Bitree Lr= (*T)->rchild,L; switch(Lr->BF) { case EH: *taller = true; (*T)->BF = RH; break; case RH: (*T)->BF=Lr->BF=EH; L_Rotate(T); break; case LH: L = Lr->lchild; switch(L->BF) { case EH: (*T)->BF=Lr->BF= EH; break; case RH: Lr->BF= EH; (*T)->BF = LH; break; case LH: (*T)->BF = LH; Lr->BF = EH; break; } L->BF = EH; R_Rotate(&Lr); L_Rotate(T); } } /*對以*T 指向的結點為根的子樹,作右單旋轉處理,處理之后,*T 指向的結點為子樹的新根*/ void R_Rotate(Bitree *T) { Bitree L=(*T)->lchild; /*L 指向*T 左子樹根結點*/ (*T)->lchild=L->rchild; /*L 的右子樹掛接*T 的左子樹*/ L->rchild=*T; *T=L; /* *L 指向新的根結點*/ } /*對以*p 指向的結點為根的子樹,作左單旋轉處理,處理之后,*p 指向的結點為子樹的新根*/ void L_Rotate(Bitree *T) { Bitree Lr=(*T)->rchild; /*Lr 指向*T 右子樹根結點*/ (*T)->rchild=Lr->lchild; /*L 的左子樹掛接*p 的右子樹*/ Lr->lchild=*T; *T=Lr; /* *L 指向新的根結點*/ }