平衡二叉樹的旋轉類型及代碼實現


參考了 : 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 }

大概就是這樣子了.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM