參考了 : http://data.biancheng.net/view/59.html 這篇文章
給大家推薦一個模擬平衡二叉樹實現的網站(超級好用):
https://www.cs.usfca.edu/~galles/visualization/AVLtree.html
最近花 了點時間 , 把上課的沒明白的平衡二叉樹自己又復習了一下,總結一下自己的平衡二叉樹;
首先, 對於平衡二叉樹 , 要明白是插入了哪個結點,然后破壞了哪個結點的平衡 , 先講一下旋轉類型:
① : 最簡單的LL型旋轉

將中間的結點往上移;
② : 最簡單的RR型旋轉

也是將中間結點上移
③ : LR型 (A類) , 我把LR型旋轉的三種情分成了ABC三類

這種LR型(A類)是在插入 3 結點的時候 , 破壞了 5 結點的平衡 , 先對 2 結點進行左旋 ,旋轉成中間的這種形態 , 在對 5 結點進行右旋
④ : LR型(B類)

這種類型的旋轉跟上面一種的差不多 , 最主要的就是注意一下 4 這個 結點的情況,最后面是放在了 5 結點的左邊
⑤ : LR型(C類)

這類是簡單的LR型 , 失衡點是 4 , 要先對 2 進行左旋, 調整成中間形態, 再對失衡點 4 進行右旋
⑥ : RL型(A類)

插入點 4 時 ,失衡點是 2 , 先對 5 進行右旋 , 再對 失衡點 2 進行左旋
⑦ : RL型(B類)

這個跟RL型(A類)不同的點就是 3 和 4 的位置
⑧ :RL型(C類)

大體可以分成這幾種旋轉類型 , 把旋轉類型理解了 , 就可以看着代碼來理解 , 我也是看着代碼才弄明白 , 所以不用 慌!
1 #include<stdlib.h> 2 #include<stdio.h> 3 #define EH 0 4 #define RH -1 /// 這三個是平衡因子 5 #define LH 1 6 7 typedef struct Node { 8 int BF ; 9 int data; 10 struct Node *left , *right; 11 }*Bitree , BitreeNode; 12 13 void R_Rotate(Bitree *T)/// 右旋 14 { 15 Bitree L = (*T)->left; 16 (*T)->left = L->right; 17 L->right = (*T); 18 *T = L; 19 } 20 void L_Rotate(Bitree *T)/// 左旋 21 { 22 Bitree L = (*T)->right; 23 (*T)->right = L->left; 24 L->left = *T; 25 *T = L; 26 } 27 void LeftBalance(Bitree *T) /// 左邊失衡了 , 進行左平衡操作 28 { 29 Bitree L , Lr; 30 L = (*T)->left; /// 失衡點 T 的左孩子進行操作 31 switch(L->BF){ /// 32 case LH: /// 左孩子的左邊重 , 進行右旋 33 (*T)->BF = L->BF = EH;/// 調節平衡因子在進行旋轉 34 R_Rotate(T); /// 右旋 35 break; 36 case RH:/// 右邊的孩子重 , 這里就是處理 LR 型的開始了, 上面的case是處理LL型的 37 Lr = L->right; /// 對 L 結點的右孩子進行分析 38 switch(Lr->BF){ 39 case EH : /// 右孩子平衡了,其實也就是沒有孩子了, 這里處理的就是我們說的 LR型(C類) 40 L->BF = EH; 41 (*T)->BF = EH;/// 先將平衡因子進行修改, 后面在進行旋轉 42 break; 43 case RH: /// 有一個右孩子, 這里就是 LR型(B類)的處理 44 L->BF = LH; 45 (*T)->BF = EH; 46 break; 47 case LH: /// LR型(A類)的處理 48 L->BF = EH; 49 (*T)->BF = RH; 50 break; 51 } 52 Lr->BF = EH; /// 修改平衡因子 , 然后進行 LR旋轉 53 L_Rotate(&(*T)->left);/// 先對子樹進行左旋,這里要寫成(*T)->left的,不能寫 &L 的, 54 ///雖然L指向(*T)的左孩子 , 但是地址不一樣!不能混 55 56 R_Rotate(T);/// 在對失衡點(*T)進行右旋 57 break; 58 } 59 } 60 ///下面是 右邊失去平衡的調整操作 ,跟上面的是一個原理,可以對着圖片的旋轉來看 61 void RightBalance(Bitree *T) 62 { 63 Bitree L , Lr; 64 Lr = (*T)->right; 65 switch(Lr->BF){ 66 case RH : 67 Lr->BF = EH; 68 (*T)->BF = EH; 69 L_Rotate(T); 70 break; 71 case LH: 72 L = Lr->left ; 73 switch(L->BF){ 74 case LH: 75 (*T)->BF = EH; 76 Lr->BF = RH; 77 break; 78 case RH :/// 79 (*T)->BF = LH; 80 Lr->BF = EH; 81 break; 82 case EH: 83 Lr->BF = EH; 84 (*T)->BF = EH; 85 break; 86 } 87 L->BF = EH; 88 R_Rotate(&(*T)->right); 89 L_Rotate(T); 90 break; 91 } 92 } 93 int Insert(Bitree *T , int data , bool *taller)/// 插入操作 94 { 95 96 if((*T)==NULL){ /// 樹空 , 添加結點 97 (*T) = (Bitree)malloc(sizeof(BitreeNode)); 98 (*T)->BF = EH; 99 (*T)->data = data; 100 (*T)->left = NULL; 101 (*T)->right = NULL; 102 *taller = true; 103 } 104 else if(data == (*T)->data){/// 樹中有這個數據點了 105 *taller = false;/// 沒有插入數據 106 return 0;/// 插入失敗 , 返回0 107 } 108 else if (data < (*T)->data){ 109 if( !Insert(&(*T)->left , data , taller)) /// 判斷插入是否成功 110 return 0; 111 if(*taller) 112 switch((*T)->BF){/// 根據 平衡因子判斷插入方向以及是否要旋轉等 113 case LH: 114 LeftBalance(T); /// 插入的話 , 就變成了 LL型 或 LR型 , 所以進行左邊平衡操作 115 *taller = false; 116 break; 117 case EH :/// 這種的話,平衡沒有破壞,就調一下平衡因子就行了 118 (*T)->BF =LH; 119 *taller = true; 120 break; 121 case RH: 122 (*T)->BF = EH; 123 *taller = false; 124 break; 125 126 } 127 } 128 else{///原理同上 129 if( !Insert(&(*T)->right , data , taller)) 130 return 0; 131 if(*taller) 132 switch((*T)->BF){ 133 case LH: 134 (*T)->BF = EH; 135 *taller = false; 136 break; 137 case EH: 138 (*T)->BF = RH; 139 *taller = true; 140 break; 141 case RH: 142 RightBalance(T); 143 *taller = false; 144 break; 145 } 146 } 147 return 1; 148 } 149 void traverse(Bitree T) 150 { 151 152 if(T){ 153 printf("%d " , T->data); 154 traverse(T->left); 155 traverse(T->right); 156 } 157 } 158 int main() 159 { 160 int a ; 161 Bitree T = NULL; 162 bool taller = false; 163 while(~scanf("%d",&a)) 164 Insert(&T , a , &taller); 165 traverse(T); 166 return 0; 167 }
大概就是這樣子了.
