平衡二叉樹

平衡二叉樹,是一種二叉排序樹,其中每個結點的左子樹和右子樹的高度差至多等於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>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章