數據結構之 平衡二叉樹


平衡二叉樹,是一種二叉排序樹,其中每個結點的左子樹和右子樹的高度差至多等於1。它是一種高度平衡的二叉排序樹。高度平衡?意思是說,要么它是一棵空樹,要么它的左子樹和右子樹都是平衡二叉樹,且左子樹和右子樹的深度之差的絕對值不超過1。

    將二叉樹上結點的左子樹深度減去右子樹深度的值稱為平衡因子BF,那么平衡二叉樹上的所有結點的平衡因子只可能是-1、0和1。只要二叉樹上有一個結點的平衡因子的絕對值大於1,則該二叉樹就是不平衡的。 

    平衡二叉樹的前提是它是一棵二叉排序樹。 

    距離插入結點最近的,且平衡因子的絕對值大於1的結點為根的子樹,稱為最小不平衡子樹。如下圖所示,當插入結點37時,距離它最近的平衡因子的絕對值超過1的結點是58。


 

1、平衡二叉樹實現原理 

    平衡二叉樹構建的基本思想就是在構建二叉排序樹的過程中,每當插入一個結點時,先檢查是否因插入而破壞了樹的平衡性,若是,則找出最小不平衡子樹。在保持二叉排序樹特性的前提下,調整最小不平衡子樹中各結點之間的鏈接關系,進行相應的旋轉,使之成為新的平衡子樹。 下面講解一個平衡二叉樹構建過程的例子。現在又a[10] = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8}需要構建二叉排序樹。在沒有學習平衡二叉樹之前,根據二叉排序樹的特性,通常會將它構建成如下左圖。雖然完全符合二叉排序樹的定義,但是對這樣高度達到8的二叉樹來說,查找是非常不利的。因此,更加期望構建出如下右圖的樣子,高度為4的二叉排序樹,這樣才可以提供高效的查找效率。

 

    現在來看看如何將一個數組構成出如上右圖的樹結構。 對於數組a的前兩位3和2,很正常地構建,到了第個數“1”時,發現此時根結點“3”的平衡因子變成了2,此時整棵樹都成了最小不平衡子樹,需要進行調整,如下圖圖1(結點左上角數字為平衡因子BF值)。因為BF為正,因此將整個樹進行右旋(順時針),此時結點2成了根結點,3成了2的右孩子,這樣三個結點的BF值均為0,非常的平衡,如下圖圖2所示。

    然后再增加結點4,平衡因子沒有改變,如上圖圖3。增加結點5時,結點3的BF值為-2,說明要旋轉了。由於BF是負值,對這棵最小平衡子樹進行左旋(逆時針旋轉),如下圖圖4,此時整個樹又達到了平衡。

 

    繼續增加結點6時,發現根結點2的BF值變成了-2,如下圖圖6所示。所以對根結點進行了左旋,注意此時本來結點3是結點3的左孩子,由於旋轉后需要滿足二叉排序樹特性,因此它成了結點2的右孩子,如圖7所示。

 

    增加結點7,同樣的左旋轉,使得整棵樹達到平衡,如下圖8和9所示。

    

    當增加結點10時,結構無變化,如圖10所示。再增加結點9,此時結點7的BF變成了-2,理論上只需要旋轉最小不平衡樹7、9、10即可,但是,如果左旋轉后,結點9變成了10的右孩子,這是不符合二叉排序樹的特性的,此時不能簡單的左旋。如圖11所示。

    仔細觀察圖11,發現根本原因在於結點7的BF是-2,而結點10的BF是1,也就是說,它們兩個一正一負,符號並不統一,而前面的幾次旋轉,無論左還是右旋,最小不平衡子樹的根結點與它的子結點符號都是相同的。這就是不能直接旋轉的關鍵。 不統一,不統一就把它們先轉到符號統一再說,於是先對結點9和結點10進行右旋,使得結點10成了9的右子樹,結點9的BF為-1,此時就與結點7的BF值符號統一了,如圖12所示。

     

    這樣再以結點7為最小不平衡子樹進行左旋,得到如下圖13。接着,插入8,情況與剛才類似,結點6的BF是-2,而它的右孩子9的BF是1,如圖14,因此首先以9為根結點,進行右旋,得到圖15,此時結點6和結點7的符號都是負,再以6為根結點左旋,最終得到最后的平衡二叉樹,如圖16所示。

  

    通過這個例子,可以發現,當最小不平衡樹根結點的平衡因子BF是大於1時,就右旋,小於-1時就左旋,如上例中的結點1、5、6、7的插入等。插入結點后,最小不平衡子樹的BF與它的子樹的BF符號相反時,就需要對結點先進行一次旋轉以使得符號相同后,再反向旋轉一次才能夠完成平衡操作,如上例中結點9、8的插入時。

    下面兩個圖講解了插入時所要做的旋轉操作的例子。《來自:http://www.cnblogs.com/guyan/archive/2012/09/03/2668399.html》



 2、平衡二叉樹算法的實現 

     首先是需要改進二叉排序樹的結點結構,增加一個bf,用來存儲平衡因子。

1
2
3
4
5
6
typedef struct BitNode
{
       int data;
       int bf;
       struct BitNode *lchild, *rchild;
}BitNode, *BiTree;
      然后對於右旋(順時針)操作,代碼如下:

1
2
3
4
5
6
7
8
void R_rotate(BiTree *t)
{
          BiTree s;
          s = (*t)->lchild;                    //s指向t的左子樹根結點
          (*t)->lchild = s->rchild;          //s的右子樹掛接為t的左子樹
          s->rchild = (*t);
          *p = s;                                //t指向新的根結點
}
      此函數代碼的意思是說,當傳入一個二叉排序樹t,將它的左孩子結點定義為s,將s的右子樹變成t的左子樹,再將t改為s的右子樹,最后將s替換為t的根結點。這樣就完成了一次右旋操作。如下圖示,圖中三角形代表子樹,N代表新增的結點。

                                    

 

    上面的例子中新增加了結點N,就是右旋操作。 

    左旋代碼如下所示。

1
2
3
4
5
6
7
8
void L_rotate(BiTree *t)
{
          BiTree s;
          s = (*t)->rchild;                    //s指向t的右子樹根結點
          (*t)->rchild = s->lchild;          //s的左子樹掛接為t的右子樹
          s->lchild = (*t);
          *p = s;                                //t指向新的根結點
}
      下面看左旋轉平衡(使左邊平衡)的處理代碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#define LH +1 /*  左高 */
#define EH 0  /*  等高 */
#define RH -1 /*  右高 */
 
/*  對以指針T所指結點為根的二叉樹作左平衡旋轉處理 */
/*  本算法結束時,指針T指向新的根結點 */
void LeftBalance(BiTree *T)
{
     BiTree L,Lr;
     L = (*T)->lchild;                                       /*  L指向T的左子樹根結點 */
     switch (L->bf)
     {
         /* 檢查T的左子樹的平衡度,並作相應平衡處理 */
          case LH:                   /* 新結點插入在T的左孩子的左子樹上,要作單右旋處理 */
             (*T)->bf=L->bf=EH;
             R_Rotate(T);
             break ;
          case RH:                   /* 新結點插入在T的左孩子的右子樹上,要作雙旋處理 */
             Lr=L->rchild;                     /* Lr指向T的左孩子的右子樹根 */
             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(&(*T)->lchild);          /* 對T的左子樹作左旋平衡處理 */
             R_Rotate(T);             /* 對T作右旋平衡處理 */
     }
}
   

    首先,定義三個常數變量,分別代碼1、0、-1。

    (1)函數被調用,傳入一個需調整平衡型的子樹T。由於LeftBalance函數被調用時,其實是已經確認當前子樹是不平衡的狀態,且左子樹的高度大於右子樹的高度。換句話說,此時T的根結點應該是平衡因子BF的值大於1的數。

    (2)將T的左孩子賦值給L。

    (3)然后是分支判斷。

    (4)當L的平衡因子為LH,即為1時,表明它與根結點的BF值符號相同,因此,將它們的BF值都改為0,並進行右旋(順時針)操作,操作方式如圖所示。

    (5)當L的平衡因子為RH時,即為-1時,表明它與根結點的BF值符號相反,此時需要做雙旋操作。針對L的右孩子的BF作判斷,修改結點T和L的BF值。將當前的Lr的BF改為0。

    (6)對根結點的左子樹進行左旋,如下圖第二圖所示。

    (7)對根結點進行右旋,如下圖第三圖所示,完成平衡操作。


    右平衡(使右邊平衡)旋轉處理的函數代碼如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*  對以指針T所指結點為根的二叉樹作右平衡旋轉處理, */
/*  本算法結束時,指針T指向新的根結點 */
void RightBalance(BiTree *T)
{
     BiTree R,Rl;
     R=(*T)->rchild; /*  R指向T的右子樹根結點 */
     switch (R->bf)
     { /*  檢查T的右子樹的平衡度,並作相應平衡處理 */
      case RH: /*  新結點插入在T的右孩子的右子樹上,要作單左旋處理 */
               (*T)->bf=R->bf=EH;
               L_Rotate(T);
               break ;
      case LH: /*  新結點插入在T的右孩子的左子樹上,要作雙旋處理 */
               Rl=R->lchild; /*  Rl指向T的右孩子的左子樹根 */
               switch (Rl->bf)
               { /*  修改T及其右孩子的平衡因子 */
                 case RH: (*T)->bf=LH;
                          R->bf=EH;
                          break ;
                 case EH: (*T)->bf=R->bf=EH;
                          break ;
                 case LH: (*T)->bf=EH;
                          R->bf=RH;
                          break ;
               }
               Rl->bf=EH;
               R_Rotate(&(*T)->rchild); /*  對T的右子樹作右旋平衡處理 */
               L_Rotate(T); /*  對T作左旋平衡處理 */
     }
}

     插入數據操作如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*  若在平衡的二叉排序樹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)->lchild=(*T)->rchild=NULL; (*T)->bf=EH;
         *taller=TRUE;
     }
     else
     {
         if (e==(*T)->data)
         {
             /*  樹中已存在和e有相同關鍵字的結點則不再插入 */
             *taller=FALSE; return FALSE;
         }
         if (e<(*T)->data)
         {
             /*  應繼續在T的左子樹中進行搜索 */
             if (!InsertAVL(&(*T)->lchild,e,taller)) /*  未插入 */
                 return FALSE;
             if (*taller)             /*   已插入到T的左子樹中且左子樹“長高” */
                 switch ((*T)->bf) /*  檢查T的平衡度 */
                 {
                     case LH:        /*  原本左子樹比右子樹高,需要作左平衡處理 */
                         LeftBalance(T);
                         *taller=FALSE; break ;
                     case EH:        /*  原本左、右子樹等高,現因左子樹增高而使樹增高 */
                         (*T)->bf=LH;
                         *taller=TRUE; break ;
                     case RH:        /*  原本右子樹比左子樹高,現左、右子樹等高 */ 
                         (*T)->bf=EH;
                         *taller=FALSE; break ;
                 }
         }
         else
         { /*  應繼續在T的右子樹中進行搜索 */
             if (!InsertAVL(&(*T)->rchild,e,taller)) /*  未插入 */
                 return FALSE;
             if (*taller)          /*  已插入到T的右子樹且右子樹“長高” */
                 switch ((*T)->bf) /*  檢查T的平衡度 */
                 {
                     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;
}

     說明:

    (1)程序開始執行時,如果T為空時,則申請內存新增一個結點。

    (2)如果表示當存在相同結點,則不需要插入。

    (3)當新結點e小於T的根結點時,則在T的左子樹查找。

    (4)遞歸調用本函數,直到找到則返回FALSE,否則說明插入結點成功,執行下面語句。

    (5)當taller為TRUE時,說明插入結點,此時需要判斷T的平衡因子,如果是1,說明左子樹高於右子樹,需要調用LeftBalance函數進行左平衡旋轉處理。如果為0或-1,則說明新插入的結點沒有讓整棵二叉排序樹失去平衡性,只需修改相關BF值即可。

    (6)說明結點e大於T的根結點的值,在T的右子樹查找。與上面類似。

 

    刪除結點的代碼如下所示。


3、C語言實現

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
<strong>#include <stdio.h>   
#include <stdlib.h>  
 
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100                     /* 存儲空間初始分配量 */
 
typedef int Status;                     /* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */
 
 
/* 二叉樹的二叉鏈表結點結構定義 */
typedef  struct BitNode                 /* 結點結構 */
{
     int data;                           /* 結點數據 */
     int bf;                             /*  結點的平衡因子 */
     struct BitNode *lchild, *rchild;    /* 左右孩子指針 */
} BitNode, *BiTree;
 
 
/* 對以p為根的二叉排序樹作右旋處理 */
/* 處理之后p指向新的樹根結點,即旋轉處理之前的左子樹的根結點 */
//右旋-順時針旋轉(如LL型就得對根結點做該旋轉)
void R_Rotate(BiTree *P)
{
     BiTree L;
     L=(*P)->lchild;                      /*  L指向P的左子樹根結點 */
     (*P)->lchild=L->rchild;               /*  L的右子樹掛接為P的左子樹 */
     L->rchild=(*P);
     *P=L;                               /*  P指向新的根結點 */
}
 
/* 對以P為根的二叉排序樹作左旋處理, */
/* 處理之后P指向新的樹根結點,即旋轉處理之前的右子樹的根結點0  */
//左旋-逆時針旋轉(如RR型就得對根結點做該旋轉)
void L_Rotate(BiTree *P)
{
     BiTree R;
     R = (*P)->rchild;                    /* R指向P的右子樹根結點 */
     (*P)->rchild = R->lchild;         /* R的左子樹掛接為P的右子樹 */
     R->lchild = (*P);
     *P = R;                             /* P指向新的根結點 */
}
 
#define LH +1                           /*  左高 */
#define EH 0                            /*  等高 */
#define RH -1                           /*  右高 */
 
/*  對以指針T所指結點為根的二叉樹作左平衡旋轉處理 */
/*  本算法結束時,指針T指向新的根結點 */
void LeftBalance(BiTree *T)
{
     BiTree L,Lr;
     L = (*T)->lchild;                    /*  L指向T的左子樹根結點 */
     switch (L->bf)
     {
         /* 檢查T的左子樹的平衡度,並作相應平衡處理 */
         case LH:                        /* 新結點插入在T的左孩子的左子樹上,要作單右旋處理 */
             (*T)->bf=L->bf=EH;
             R_Rotate(T);
             break ;
         case RH:                        /* 新結點插入在T的左孩子的右子樹上,要作雙旋處理 */ //
             Lr=L->rchild;                /* Lr指向T的左孩子的右子樹根 */
             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(&(*T)->lchild); /* 對T的左子樹作左旋平衡處理 */
             R_Rotate(T);                /* 對T作右旋平衡處理 */
     }
}
 
/*  對以指針T所指結點為根的二叉樹作右平衡旋轉處理, */
/*  本算法結束時,指針T指向新的根結點 */
void RightBalance(BiTree *T)
{
     BiTree R,Rl;
     R=(*T)->rchild;                      /*  R指向T的右子樹根結點 */
     switch (R->bf)
     {
         /*  檢查T的右子樹的平衡度,並作相應平衡處理 */
         case RH:                        /*  新結點插入在T的右孩子的右子樹上,要作單左旋處理 */
             (*T)->bf=R->bf=EH;
             L_Rotate(T);
             break ;
         case LH:                        /*  新結點插入在T的右孩子的左子樹上,要作雙旋處理 */ //最小不平衡樹的根結點為負,其右孩子為正
             Rl=R->lchild;                /*  Rl指向T的右孩子的左子樹根 */
             switch (Rl->bf)
             {
                 /*  修改T及其右孩子的平衡因子 */
                 case RH:
                     (*T)->bf=LH;
                     R->bf=EH;
                     break ;
                 case EH:
                     (*T)->bf=R->bf=EH;
                     break ;
                 case LH:
                     (*T)->bf=EH;
                     R->bf=RH;
                     break ;
             }
             Rl->bf=EH;
             R_Rotate(&(*T)->rchild); /*  對T的右子樹作右旋平衡處理 */
             L_Rotate(T);                /*  對T作左旋平衡處理 */
     }
}
 
/*  若在平衡的二叉排序樹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)->lchild=(*T)->rchild=NULL;
         (*T)->bf=EH;
         *taller=TRUE;
     }
     else
     {
         if (e==(*T)->data)
         {
             /*  樹中已存在和e有相同關鍵字的結點則不再插入 */
             *taller=FALSE;
             return FALSE;
         }
         if (e<(*T)->data)
         {
             /*  應繼續在T的左子樹中進行搜索 */
             if (!InsertAVL(&(*T)->lchild, e, taller)) /*  未插入 */
                 return FALSE;
             if (*taller)                             /*   已插入到T的左子樹中且左子樹“長高” */
                 switch ((*T)->bf)                 /*  檢查T的平衡度 */
                 {
                     case LH:                        /*  原本左子樹比右子樹高,需要作左平衡處理 */
                         LeftBalance(T);
                         *taller=FALSE;
                         break ;
                     case EH:                        /*  原本左、右子樹等高,現因左子樹增高而使樹增高 */
                         (*T)->bf=LH;
                         *taller=TRUE;
                         break ;
                     case RH:                        /*  原本右子樹比左子樹高,現左、右子樹等高 */ 
                         (*T)->bf=EH;
                         *taller=FALSE;
                         break ;
                 }
         }
         else
         {
             /*  應繼續在T的右子樹中進行搜索 */
             if (!InsertAVL(&(*T)->rchild,e, taller)) /*  未插入 */
             {
                 return FALSE;
             }
             if (*taller)                             /*  已插入到T的右子樹且右子樹“長高” */
             {
                 switch ((*T)->bf)                 /*  檢查T的平衡度 */
                 {
                     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;
}
 
 
/*
若在平衡的二叉排序樹t中存在和e有相同關鍵字的結點,則刪除之
並返回TRUE,否則返回FALSE。若因刪除而使二叉排序樹
失去平衡,則作平衡旋轉處理,布爾變量shorter反映t變矮與否
*/
int deleteAVL(BiTree *t, int key, int *shorter)
{
     if (*t == NULL)                                      //不存在該元素
     {
         return FALSE;                                   //刪除失敗
     }
     else if (key == (*t)->data)                           //找到元素結點
     {
         BitNode *q = NULL;
         if ((*t)->lchild == NULL)                     //左子樹為空
         {
             q = (*t);
             (*t) = (*t)->rchild;
             free (q);
             *shorter = TRUE;
         }
         else if ((*t)->rchild == NULL)                    //右子樹為空
         {
             q = (*t);
             (*t) = (*t)->lchild;
             free (q);
             *shorter = TRUE;
         }
         else                                            //左右子樹都存在,
         {
             q = (*t)->lchild;
             while (q->rchild)
             {
                 q = q->rchild;
             }
             (*t)->data = q->data;
             deleteAVL(&(*t)->lchild, q->data, shorter);   //在左子樹中遞歸刪除前驅結點
         }
     }
     else if (key < (*t)->data)                         //左子樹中繼續查找
     {
         if (!deleteAVL(&(*t)->lchild, key, shorter))
         {
             return FALSE;
         }
         if (*shorter)
         {
             switch ((*t)->bf)
             {
             case LH:
                 (*t)->bf = EH;
                 *shorter = TRUE;
                 break ;
             case EH:
                 (*t)->bf = RH;
                 *shorter = FALSE;
                 break ;
             case RH:
                 RightBalance(&(*t));        //右平衡處理
                 if ((*t)->rchild->bf == EH)    //注意這里,畫圖思考一下
                     *shorter = FALSE;
                 else
                     *shorter = TRUE;
                 break ;
             }
         }
     }
     else                                //右子樹中繼續查找
     {
         if (!deleteAVL(&(*t)->rchild, key, shorter))
         {
             return FALSE;
         }
         if (shorter)
         {
             switch ((*t)->bf)
             {
             case LH:
                 LeftBalance(&(*t));         //左平衡處理
                 if ((*t)->lchild->bf == EH)  //注意這里,畫圖思考一下
                     *shorter = FALSE;
                 else
                     *shorter = TRUE;
                 break ;
             case EH:
                 (*t)->bf = LH;
                 *shorter = FALSE;
                 break ;
             case RH:
                 (*t)->bf = EH;
                 *shorter = TRUE;
                 break ;
             }
         }
     }
     return TRUE;
}
 
void InOrderTraverse(BiTree t)
{
     if (t)
     {
         InOrderTraverse(t->lchild);
         printf ( "%d  " , t->data);
         InOrderTraverse(t->rchild);
     }
}
 
 
int main( void )
{   
     int i;
     int a[10]={3,2,1,4,5,6,7,10,9,8};
     BiTree T=NULL;
     Status taller;
     for (i=0;i<10;i++)
     {
         InsertAVL(&T,a[i],&taller);
     }
     printf ( "中序遍歷二叉平衡樹:\n" );
     InOrderTraverse(T);
     printf ( "\n" );
     printf ( "刪除結點元素5后中序遍歷:\n" );
     int shorter;
     deleteAVL(&T, 5, &shorter);
     InOrderTraverse(T);
     printf ( "\n" );
     return 0;
}</strong>


免責聲明!

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



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