因為二叉樹本身就是個遞歸的概念,所以在構建平衡二叉樹的時候,應時刻記得遞歸這個概念。
同樣的序列,因為排序不同,可能會生成不同的二叉排序樹,查找效率性對就不一定了,如:1-9這些數字就可以生成下面兩種樹。
第二種就是一個極端的情況,如果要查找9,就需要進行比較8次,效率很低。由此就引出,平衡二叉樹的概念。
什么是平衡二叉樹?
希望對一個序列,進行查找,最好的就是將其構建成一個平衡二叉樹即AVL樹。
但是怎么構建平衡二叉排序樹?
前提:必須是一棵樹。(類似於:只有先保證他是一個人,才難說他是一個什么樣的男人。嘻嘻,這個比喻不是那么准確啦)
下面有一個題目:
怎么將左圖構建成右圖的平衡二叉樹呢?
可見,左圖和右圖的不同就在於是否是平衡的。左圖中節點9的平衡因子是2,是個不平衡點。
構造平衡二叉樹:
如果在一棵平衡的二叉搜索樹中,插入一個新節點時,造成了不平衡。此時必須調整樹的結構,使之平衡化。
平衡旋轉有兩類:
--單旋轉(左旋和右旋)
--雙旋轉(左右旋和右左旋)
每插入一個新節點時,AVL樹中相關節點的平衡狀態會發生改變。因此,在插入一個新節點后,需要從插入位置沿着通向根的路徑回溯,檢查各節點的平衡因子。如果在某一節點發現此樹不平衡,停止回溯。
從發生不平衡的節點起,沿着剛才回溯的路徑取直接下兩層的節點。
(1)如果這三個節點處在一條直線上,則采用單旋轉進行平衡化。單旋轉可按方向分為左單旋轉和右單旋轉。
(2)如果這三個節點處在一條折線上,則采用雙旋轉進行平衡化。單旋轉可按方向分為先左后右旋轉和先右后左旋轉。
下面舉兩個簡單的例子,便於理解。
1:a[10]={3,2,1,4,5,6,7,10,9,8};對於這壓樣一個一維數組,構建二叉平衡樹。
此時構建過程已經完成。
例子2:
下面是代碼實現:
1 /*平衡二叉樹的實現原理 2 時間:2015-6-21 3 ***/ 4 #define LH 1//左子樹高 5 #define EH 1//左右子樹登高 6 #define RH 1//右子樹 7 8 typedef struct BITNode{ 9 int data; 10 int bf; 11 struct BITNode*lchild,*rchild; 12 }BITNode,*BiTree; 13 //右旋操作 14 void R_Rotate(BiTree *p) 15 { 16 BiTree L; 17 L=(*p)->lchild; 18 (*p)->lchild=L->rchild; 19 L->rchild=(*p); 20 *p=L; 21 } 22 //左旋操作 23 void L_Rotate(BiTree *p) 24 { 25 BiTree L; 26 L=(*p)->rchild; 27 (*p)->rchild=L->lchild; 28 L->lchild=(*p); 29 *p=L; 30 } 31 //左平衡 32 void LeftBalance(BiTree *T) 33 { 34 BiTree L,lr; 35 L=(*T)->lchild; 36 switch(L-bf) 37 { 38 case LH; 39 (*T)->bf=L-bf=EH; 40 R_RETATE(T) 41 break; 42 case RH; 43 lr=L->rchild; 44 switch(Lr-bf) 45 { 46 case LH; 47 (*T)->bf=RH; 48 L->bf=EH; 49 break; 50 case EH; 51 (*T)->bf=L-bf=EH; 52 break; 53 case RH; 54 (*T)->bf=EH; 55 L-bf=LH; 56 break; 57 } 58 lR->bf=EH; 59 L_Rotate(&(*T)->lchild); 60 R_Rotate(T); 61 } 62 63 } 64 int InsertAVL(BITree *T,int n,int *taller)//taller用於判斷插入節點后,樹長高了沒有 65 { 66 if(!*T) 67 { 68 *T=(BiTree)malloc(sizeod(BITNode)); 69 (*T)->data=e; 70 (*T)->lchild=(*T)->rchild=NULL; 71 (*T)->bf=EH; 72 *taller=TRUE; 73 } 74 else{ 75 if(e==(*T)->data) 76 { 77 *taller=FALSE; 78 return FALSE; 79 } 80 if(e<(*T)->data) 81 { 82 if(!InsertAVL(&(*T))->lchild,e,taller) 83 { 84 return FALSE; 85 } 86 if(*taller)//判斷樹的長勢 87 { 88 switch((*T)->bf) 89 { 90 case LH: 91 LeftBalance(T); 92 *taller=FALSE; 93 break; 94 case EH: 95 (*T)->bf=EH; 96 *taller=TRUE; 97 break; 98 case RH: 99 (*T)->bf=EH; 100 *taller=FALSE; 101 102 } 103 } 104 105 } 106 else 107 { 108 if(!InsertAVL(&(*T))->rchild,e,taller) 109 { 110 return FALSE; 111 } 112 if(*taller)//判斷樹的長勢 113 { 114 switch((*T)->bf) 115 { 116 case LH: 117 (*T)->bf=EH; 118 *taller=FALSE; 119 break; 120 case EH: 121 (*T)->bf=EH; 122 *taller=TRUE; 123 break; 124 case RH: 125 RightBalance(T); 126 (*T)->bf=EH; 127 *taller=FALSE; 128 129 } 130 } 131 132 } 133 } 134 }