平衡二叉树(AVL)的实现,附可运行C语言代码

最近几月一直在自学C语言和数据结构,先是写了排序二叉树,觉得平衡二叉树作为一个经典数据结构,有必要实现一下。

网上看了些资料,在AVL和红黑树之间考虑,最后个人还是倾向于AVL。

不同于标准AVL的是,笔者没有使用平衡因子,直接根据左右孩子的高度差值判断是否平衡。整个平衡二叉树是在普通二叉查找树的基础上修改得到的,对于学习数据结构的同学来说,这样逐步提高难度,写起来挑战性没那么大。

代码经测试是可以运行,并实现插入、删除、修改节点时都可以保持平衡。相对于普通二叉查找树,AVL在查找时效率高耗时短,但为了保持高度平衡,必须牺牲插入和删除操作的复杂度。本文将分步讲解如何编写平衡二叉树,全文最后附有完整代码。

当左右子树的高度差超过1时(即≥2,在实际处理时,等于2即为不平衡,进行调整操作,所以不会出现大于2的情况),整棵树失去平衡。写代码之前先了解AVL是如何使二叉树保持平衡,这里涉及到对节点的旋转操作,分四种情况,左左,右右,左右,右左。下面分别解释:

一、左左单旋转

在节点x的左孩子插入节点b

①x无右孩子,旋转节点a即可达到平衡

②x有右孩子c,旋转节点a后,根据a>c>x,需将节点c移动到a的左子树

《平衡二叉树(AVL)的实现,附可运行C语言代码》

函数代码如下:

 1 static BTNode *singleRotateLL(BTree *BT, BTNode *phead)
 2 {//不平衡情况为左左的单旋转操作
 3     BTNode *temp;
 4 
 5     if(phead == NULL)
 6         return 0;
 7 
 8     temp = phead->lchild;
 9     
10     if(temp->rchild != NULL){
11         phead->lchild = temp->rchild;
12         phead->lchild->height = tree_node_height(BT, phead->lchild);
13     }
14     else
15         phead->lchild = NULL;
16 
17     temp->rchild = phead;
18     if(temp->rchild->data == BT->phead->data){
19         BT->phead = temp;
20     }
21     phead = temp;
22     temp->rchild->height = tree_node_height(BT, temp->rchild);
23     temp->height = tree_node_height(BT, temp);
24     phead->height = tree_node_height(BT, phead);
25     
26     return phead;
27 }

二、右右单旋转

在节点x的右孩子插入节点b

①x无左孩子,旋转节点a即可达到平衡

②x有左孩子c,旋转节点a后,根据x>c>a,需将节点c移动到a的右子树

《平衡二叉树(AVL)的实现,附可运行C语言代码》

函数代码如下:

 1 static BTNode *singleRotateRR(BTree *BT, BTNode *phead)
 2 {//不平衡情况为右右的单旋转操作
 3     BTNode *temp;
 4 
 5     if(phead == NULL)
 6         return 0;
 7 
 8     temp = phead->rchild;
 9 
10     if(temp->lchild != NULL){
11         phead->rchild = temp->lchild;
12         phead->rchild->height = tree_node_height(BT, phead->rchild);
13     }
14     else
15         phead->rchild = NULL;
16 
17     temp->lchild = phead;
18     if(temp->lchild->data == BT->phead->data){
19         BT->phead = temp;
20     }
21     phead = temp;
22     temp->lchild->height = tree_node_height(BT, temp->lchild);
23     temp->height = tree_node_height(BT, temp);
24     phead->height = tree_node_height(BT, phead);
25 
26     return phead;
27 }

注:需要注意的是节点旋转后,节点赋值和高度的更新,初学者很容易忽略或是弄错赋值顺序

三、左右双旋转

在节点x的右孩子插入节点b

①x无左孩子,②x有左孩子c,这两种情况的处理相同,首先对x节点进行右右单旋转操作,然后对a节点进行左左单旋转操作

《平衡二叉树(AVL)的实现,附可运行C语言代码》

函数代码如下:

 1 static BTNode *doubleRotateLR(BTree *BT, BTNode *phead)
 2 {//不平衡情况为左右的双旋转操作
 3     BTNode *temp;
 4 
 5     if(phead == NULL)
 6         return 0;
 7 
 8     temp = phead->lchild;    
 9     phead->lchild = singleRotateRR(BT, temp);
10     temp = phead;
11     phead = singleRotateLL(BT, temp);
12 
13     return phead;
14 }

四、右左双旋转

在节点x的右孩子插入节点b

①x无右孩子,②x有右孩子c,这两种情况的处理相同,首先对x节点进行左左单旋转操作,然后对a节点进行右右单旋转操作

《平衡二叉树(AVL)的实现,附可运行C语言代码》

函数代码如下:

 1 static BTNode *doubleRotateRL(BTree *BT, BTNode *phead)
 2 {//不平衡情况为右左的双旋转操作
 3     BTNode *temp;
 4 
 5     if(phead == NULL)
 6         return 0;
 7 
 8     temp = phead->rchild;
 9     phead->rchild = singleRotateLL(BT, temp);
10     temp = phead;
11     phead = singleRotateRR(BT, temp);
12 
13     return phead;
14 }

 

弄清楚了怎样通过旋转达到平衡状态,接下来一步一步构造平衡二叉树。

第一步,我们要在二叉树的节点中加一个属性:高度,在后面的插入和删除函数中将会用到。

结构体代码如下:

1 typedef struct _BTNode{
2     TYPE data;
3     int height;         
4     struct _BTNode *lchild;
5     struct _BTNode *rchild;
6 }BTNode;

 

第二步,需要添加三个辅助函数,一是求节点的高度,而是遍历求树中每个节点的高度(在删除函数中会用到),三是求两个高度的最大值。

 1 static int tree_node_height(BTree *BT, BTNode *phead)
 2 {//求节点的高度,写成函数解决指针为空的情况,默认空节点的高度为-1,只有一个根节点的节点的高度为0,每多一层高度加1
 3     if(phead != NULL){
 4         if(phead->lchild == NULL && phead->rchild == NULL){
 5             return 0;
 6         }
 7         else{
 8             return phead->height = max_height(tree_node_height(BT, phead->lchild), tree_node_height(BT, phead->rchild)) + 1;
 9         }
10     }
11     else{
12         return -1;
13     }
14 }
15 
16 static void tree_height(BTree *BT, BTNode *phead)
17 {//遍历求树中每个节点的高度
18     if(phead == NULL)
19         return;
20 
21     tree_node_height(BT, phead);
22     if(phead->lchild != NULL)
23         tree_node_height(BT, phead->lchild);
24     if(phead->rchild != NULL)
25         tree_node_height(BT, phead->rchild);
26 }
27 
28 static int max_height(int height1, int height2)
29 {//求两个高度的最大值
30     if(height1 > height2)
31         return height1;
32     else
33         return height2;
34 }

 第三步,插入

 插入操作与二叉查找树的操作基本相同,只是在插入后需判断是否平衡,如果不平衡,进行旋转调整。因为BTNode没有使用父节点属性,所以需要用变量存储插入位置,以便调整后可以接回到二叉树上。树顶的根节点需特殊处理

 1 static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value)
 2 {//按序插入结点
 3     if(phead == NULL)
 4         return 0;
 5 
 6     if(phead->data == value)
 7         return 0;
 8 
 9     else{
10         if(phead->data > value){
11             if(phead->lchild == NULL){
12                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));
13                 newnode->data = value;
14                 newnode->lchild = newnode->rchild = NULL;
15                 phead->lchild = newnode;
16             }
17             else{
18                 tree_add(BT, phead->lchild, value);
19 
20                 //判断插入节点后是否平衡,并调整
21                 BTNode *root;
22                 if(phead = BT->phead)
23                     root = phead;
24                 else
25                     root = phead->lchild;
26             
27                 if(tree_node_height(BT, root->lchild) - tree_node_height(BT, root->rchild) == 2){
28                     if(root->lchild->data > value){
29                         root = singleRotateLL(BT, root);
30                     }
31                     else{
32                         root = doubleRotateLR(BT, root);
33                     }
34                 }
35                 phead = root;
36             }
37         }
38         else{
39             if(phead->rchild == NULL){
40                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));
41                 newnode->data = value;
42                 newnode->lchild = newnode->rchild = NULL;
43                 phead->rchild = newnode;                    
44             }
45             else{
46                 tree_add(BT, phead->rchild, value);
47                 
48                 //判断插入节点后是否平衡,并调整
49                 BTNode *root;
50                 if(phead = BT->phead)
51                     root = phead;
52                 else
53                     root = phead->rchild;
54                     
55                 if(tree_node_height(BT, root->rchild) - tree_node_height(BT, root->lchild) == 2){
56                     if(root->rchild->data < value){
57                         root = singleRotateRR(BT, root);
58                     }
59                     else{
60                         root = doubleRotateRL(BT, root);
61                     }
62                 }
63                 phead = root;
64             }            
65         }
66             phead->height = tree_node_height(BT, phead);
67             return 1;
68     }
69 
70     return 0;
71 }

第四步,删除

平衡二叉树的删除操作比插入更复杂,因为删除后会引起一系列节点高度的改变,删除后将剩余子树接回二叉树时,要分三种情况处理,被删除节点是:顶部根节点、底部叶子(无子树)、普通节点。

 1 static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value)
 2 {//删除结点
 3     BTNode *temp;
 4     BTNode *root;
 5     int flag;        //flag标记被删除的节点,默认顶部节点flag为0,左边节点flag为-1,右边节点flag为1
 6 
 7     if(*phead == NULL)
 8         return 0;
 9         
10     if(*phead == BT->phead){
11         flag = 0;
12         root = *phead;
13     }
14 
15     else if((*phead)->lchild != NULL){
16         flag = -1;
17         root = (*phead)->lchild;
18     }
19 
20     else if((*phead)->rchild != NULL){
21         flag = 1;
22         root = (*phead)->rchild;
23     }
24     else if((*phead)->lchild == NULL && (*phead)->rchild == NULL)
25         root = *phead;
26     
27     if(root->data == value){
28         if(root->lchild != NULL){
29             temp = BT->search_max(BT, &root->lchild, 1);
30             temp->lchild = root->lchild;
31              temp->rchild = root->rchild;
32             free(root);
33             root = temp;
34             if(flag == 0)
35                 BT->phead = root;
36             else
37                 (*phead)->lchild = root;
38         }
39         else if(root->rchild != NULL){
40             temp = BT->search_min(BT, &root->rchild, 1);   
41             temp->lchild = root->lchild;
42             temp->rchild = root->rchild;
43             free(root);
44             root = temp;
45             if(flag == 0)
46                 BT->phead = root;
47             else
48                 (*phead)->rchild = root;
49         }
50         else{
51             if(flag == 0)
52                 free(*phead);
53             else if(flag = -1){
54                 free((*phead)->lchild);
55                 (*phead)->lchild = NULL;
56             }
57             else if(flag = 1){
58                 free((*phead)->rchild);
59                 (*phead)->rchild = NULL;
60             }
61         }
62          
63         tree_height(BT, BT->phead);    //删除节点后,求每个节点的新高度
64 
65         if(flag == 0)
66             return 1;
67         if(flag == -1){
68             if(tree_node_height(BT, (*phead)->rchild) - tree_node_height(BT, (*phead)->lchild) == 2){
69                 if((*phead)->rchild->rchild != NULL){
70                     root = singleRotateRR(BT, *phead);
71                 }
72                 else{
73                     root = doubleRotateRL(BT, *phead);
74                 }
75             }
76         }
77         else{
78             if(tree_node_height(BT, (*phead)->lchild) - tree_node_height(BT, (*phead)->rchild) == 2){
79                 if((*phead)->lchild->lchild != NULL){
80                     root = singleRotateLL(BT, *phead);
81                 }
82                 else{
83                     root = doubleRotateLR(BT, *phead);
84                 }
85             }
86         }
87             
88         return 1;
89     }
90     else if(root->data > value)
91         return BT->del(BT, &root->lchild, value);
92     else
93         return BT->del(BT, &root->rchild, value);
94 
95     return 0;
96 }

 

除了插入和删除操作,其他操作均与普通二叉查找树一样。

如果读者发现错误或有更好的处理方法,请指出,以便修改完善。 

 

头文件binary.h代码:

《平衡二叉树(AVL)的实现,附可运行C语言代码》
《平衡二叉树(AVL)的实现,附可运行C语言代码》

 1 #ifndef BINARY_H
 2 #define BINARY_H
 3 
 4 typedef int TYPE;
 5 typedef int BOOL;
 6 
 7 typedef struct _BTNode{
 8     TYPE data;
 9     int height;         
10     struct _BTNode *lchild;
11     struct _BTNode *rchild;
12 }BTNode;
13 
14 typedef struct _BTree{
15     BTNode *phead;    
16 
17     void(*init)(struct _BTree *BT, TYPE head_value);
18     void(*exit)(struct _BTree *BT);
19     void(*print)(struct _BTree *BT, BTNode *phead);
20 
21     BOOL(*add)(struct _BTree *BT, BTNode *phead, TYPE value);
22     BOOL(*del)(struct _BTree *BT, BTNode **phead, TYPE value);
23     BOOL(*del_tree)(struct _BTree *BT, BTNode **phead);
24     BOOL(*alter)(struct _BTree *BT, BTNode *phead, TYPE value, TYPE new_value);
25     BTNode *(*search)(struct _BTree *BT, BTNode *phead, TYPE value);
26 
27     BTNode *(*search_min)(struct _BTree *BT, BTNode **phead, int flag);
28     BTNode *(*search_max)(struct _BTree *BT, BTNode **phead, int flag);    
29 
30     void(*pre_traverse)(struct _BTree *BT, BTNode *phead);
31     void(*mid_traverse)(struct _BTree *BT, BTNode *phead);
32     void(*last_traverse)(struct _BTree *BT, BTNode *phead);
33 
34     //以下为实现AVL所需函数
35     int (*node_height)(_BTree *BT, BTNode *phead);
36     void (*height)(_BTree *BT, BTNode *phead);
37     int (*max_height)(int height1, int height2);
38     BTNode *(*singleRotateLL)(_BTree *BT, BTNode *phead);
39     BTNode *(*singleRotateRR)(_BTree *BT, BTNode *phead);
40     BTNode *(*doubleRotateLR)(_BTree *BT, BTNode *phead);
41     BTNode *(*doubleRotateRL)(_BTree *BT, BTNode *phead);
42 }BTree;
43 
44 void tree_init(BTree *BT, TYPE value);
45 void tree_exit(BTree *BT);
46 
47 #endif

View Code

源文件binary.cpp代码:

《平衡二叉树(AVL)的实现,附可运行C语言代码》
《平衡二叉树(AVL)的实现,附可运行C语言代码》

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 
  5 #include "binary.h"
  6 
  7 void tree_init(BTree *BT, TYPE head_value);
  8 void tree_exit(BTree *BT);
  9 void tree_print(BTree *BT, BTNode *phead);
 10 static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value);
 11 static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value);
 12 static BOOL tree_del_tree(BTree *BT, BTNode **phead);
 13 static BOOL tree_alter(BTree *BT, BTNode *phead, TYPE value, TYPE new_value);
 14 static BTNode *tree_search(BTree *BT, BTNode *phead, TYPE value);
 15 static BTNode *tree_search_min(BTree *BT, BTNode **phead, int flag);
 16 static BTNode *tree_search_max(BTree *BT, BTNode **phead, int flag);
 17 static void tree_pre_traverse(BTree *BT, BTNode *phead);
 18 static void tree_mid_traverse(BTree *BT, BTNode *phead);
 19 static void tree_last_traverse(BTree *BT, BTNode *phead);
 20 
 21 //以下为实现AVL所需函数
 22 static int tree_node_height(BTree *BT, BTNode *phead);
 23 static void tree_height(BTree *BT, BTNode *phead);
 24 static int max_height(int height1, int height2);
 25 static BTNode *singleRotateLL(BTree *BT, BTNode *phead);
 26 static BTNode *singleRotateRR(BTree *BT, BTNode *phead);
 27 static BTNode *doubleRotateLR(BTree *BT, BTNode *phead);
 28 static BTNode *doubleRotateRL(BTree *BT, BTNode *phead);
 29 
 30 
 31 void tree_init(BTree *BT, TYPE head_value)
 32 {//初始化
 33     BT->phead = (BTNode*)calloc(1, sizeof(BTNode));
 34     BT->phead->data = head_value;
 35     
 36     BT->phead->lchild = BT->phead->rchild = NULL;
 37 
 38     BT->add = tree_add;
 39     BT->del = tree_del;
 40     BT->print = tree_print;
 41     BT->del_tree = tree_del_tree;
 42     BT->alter = tree_alter;
 43     BT->search = tree_search;
 44     BT->search_min = tree_search_min;
 45     BT->search_max = tree_search_max;
 46     BT->pre_traverse = tree_pre_traverse;
 47     BT->mid_traverse = tree_mid_traverse;
 48     BT->last_traverse = tree_last_traverse;
 49     BT->exit = tree_exit;
 50 
 51     BT->node_height = tree_node_height;
 52     BT->height = tree_height;
 53     BT->max_height = max_height;
 54     BT->singleRotateLL = singleRotateLL;
 55     BT->singleRotateRR = singleRotateRR;
 56     BT->doubleRotateLR = doubleRotateLR;
 57     BT->doubleRotateRL = doubleRotateRL;
 58 }
 59 
 60 void tree_exit(BTree *BT)
 61 {//结束操作
 62     if(BT != NULL)
 63         BT->del_tree(BT, &BT->phead);
 64 }
 65 
 66 void tree_print(BTree *BT, BTNode *phead)
 67 {//打印结点
 68     if(phead != NULL)
 69         printf("%d\n", phead->data);
 70 }
 71 
 72 static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value)
 73 {//按序插入结点
 74     if(phead == NULL)
 75         return 0;
 76 
 77     if(phead->data == value)
 78         return 0;
 79 
 80     else{
 81         if(phead->data > value){
 82             if(phead->lchild == NULL){
 83                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));
 84                 newnode->data = value;
 85                 newnode->lchild = newnode->rchild = NULL;
 86                 phead->lchild = newnode;
 87             }
 88             else{
 89                 tree_add(BT, phead->lchild, value);
 90 
 91                 //判断插入节点后是否平衡,并调整
 92                 BTNode *root;
 93                 if(phead = BT->phead)
 94                     root = phead;
 95                 else
 96                     root = phead->lchild;
 97             
 98                 if(tree_node_height(BT, root->lchild) - tree_node_height(BT, root->rchild) == 2){
 99                     if(root->lchild->data > value){
100                         root = singleRotateLL(BT, root);
101                     }
102                     else{
103                         root = doubleRotateLR(BT, root);
104                     }
105                 }
106                 phead = root;
107             }
108         }
109         else{
110             if(phead->rchild == NULL){
111                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));
112                 newnode->data = value;
113                 newnode->lchild = newnode->rchild = NULL;
114                 phead->rchild = newnode;                    
115             }
116             else{
117                 tree_add(BT, phead->rchild, value);
118                 
119                 //判断插入节点后是否平衡,并调整
120                 BTNode *root;
121                 if(phead = BT->phead)
122                     root = phead;
123                 else
124                     root = phead->rchild;
125                     
126                 if(tree_node_height(BT, root->rchild) - tree_node_height(BT, root->lchild) == 2){
127                     if(root->rchild->data < value){
128                         root = singleRotateRR(BT, root);
129                     }
130                     else{
131                         root = doubleRotateRL(BT, root);
132                     }
133                 }
134                 phead = root;
135             }            
136         }
137             phead->height = tree_node_height(BT, phead);
138             return 1;
139     }
140 
141     return 0;
142 }
143 
144 static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value)
145 {//删除结点
146     BTNode *temp;
147     BTNode *root;
148     int flag;        //flag标记被删除的节点,默认顶部节点flag为0,左边节点flag为-1,右边节点flag为1
149 
150     if(*phead == NULL)
151         return 0;
152         
153     if(*phead == BT->phead){
154         flag = 0;
155         root = *phead;
156     }
157 
158     else if((*phead)->lchild != NULL){
159         flag = -1;
160         root = (*phead)->lchild;
161     }
162 
163     else if((*phead)->rchild != NULL){
164         flag = 1;
165         root = (*phead)->rchild;
166     }
167     else if((*phead)->lchild == NULL && (*phead)->rchild == NULL)
168         root = *phead;
169     
170     if(root->data == value){
171         if(root->lchild != NULL){
172             temp = BT->search_max(BT, &root->lchild, 1);
173             temp->lchild = root->lchild;
174              temp->rchild = root->rchild;
175             free(root);
176             root = temp;
177             if(flag == 0)
178                 BT->phead = root;
179             else
180                 (*phead)->lchild = root;
181         }
182         else if(root->rchild != NULL){
183             temp = BT->search_min(BT, &root->rchild, 1);   
184             temp->lchild = root->lchild;
185             temp->rchild = root->rchild;
186             free(root);
187             root = temp;
188             if(flag == 0)
189                 BT->phead = root;
190             else
191                 (*phead)->rchild = root;
192         }
193         else{
194             if(flag == 0)
195                 free(*phead);
196             else if(flag = -1){
197                 free((*phead)->lchild);
198                 (*phead)->lchild = NULL;
199             }
200             else if(flag = 1){
201                 free((*phead)->rchild);
202                 (*phead)->rchild = NULL;
203             }
204         }
205          
206         tree_height(BT, BT->phead);    //删除节点后,求每个节点的新高度
207 
208         if(flag == 0)
209             return 1;
210         if(flag == -1){
211             if(tree_node_height(BT, (*phead)->rchild) - tree_node_height(BT, (*phead)->lchild) == 2){
212                 if((*phead)->rchild->rchild != NULL){
213                     root = singleRotateRR(BT, *phead);
214                 }
215                 else{
216                     root = doubleRotateRL(BT, *phead);
217                 }
218             }
219         }
220         else{
221             if(tree_node_height(BT, (*phead)->lchild) - tree_node_height(BT, (*phead)->rchild) == 2){
222                 if((*phead)->lchild->lchild != NULL){
223                     root = singleRotateLL(BT, *phead);
224                 }
225                 else{
226                     root = doubleRotateLR(BT, *phead);
227                 }
228             }
229         }
230             
231         return 1;
232     }
233     else if(root->data > value)
234         return BT->del(BT, &root->lchild, value);
235     else
236         return BT->del(BT, &root->rchild, value);
237 
238     return 0;
239 }
240 
241 static BOOL tree_del_tree(BTree *BT, BTNode **phead)
242 {//删除二叉树
243     if(*phead == NULL)
244         return 0;
245     
246     if((*phead)->lchild != NULL)
247         BT->del_tree(BT, &(*phead)->lchild);
248     if((*phead)->rchild != NULL)
249         BT->del_tree(BT, &(*phead)->rchild);
250 
251     free(*phead);
252     *phead = NULL;
253 
254     return 1;
255 }
256 
257 static BOOL tree_alter(BTree *BT, BTNode *phead, TYPE value, TYPE new_value)
258 {//更改结点的值(先删除,后插入)
259     if(phead == NULL)
260         return 0;
261 
262     if(value == new_value)
263         return 1;
264 
265     if(BT->del(BT, &phead, value) != 0){
266         if(BT->add(BT, phead, new_value) != 0)
267             return 1;
268         else
269             return 0;
270     }
271     else
272         return 0;
273 }
274 
275 static BTNode *tree_search(BTree *BT, BTNode *phead, TYPE value)
276 {//查找结点
277     BTNode *temp;
278 
279     if(phead == NULL)
280         return NULL;
281 
282     if(phead->data == value)
283         return phead;
284     if(phead->lchild != NULL){
285         temp = BT->search(BT, phead->lchild, value);
286         if(temp != NULL)
287             return temp;
288     }
289     if(phead->rchild != NULL){
290         temp = BT->search(BT, phead->rchild, value);
291         if(temp != NULL)
292             return temp;
293     }
294 
295     return NULL;
296 }
297 
298 static BTNode *tree_search_min(BTree *BT, BTNode **phead, int flag)
299 {//查找最小结点
300     BTNode *temp;
301 
302     if(*phead == NULL)
303         return NULL;
304 
305     if((*phead)->lchild == NULL){
306         temp = *phead;
307         if(flag == 1)
308             *phead = (*phead)->rchild;
309         return temp;
310     }
311     else
312         return BT->search_min(BT, &(*phead)->lchild, flag);
313 }
314 
315 static BTNode *tree_search_max(BTree *BT, BTNode **phead, int flag)
316 {//查找最大结点
317     BTNode *temp;
318 
319     if(*phead == NULL)
320         return NULL;
321 
322     if((*phead)->rchild == NULL){
323         temp = *phead;
324         if(flag == 1)
325             *phead = (*phead)->lchild;
326         return temp;
327     }
328     else
329         return BT->search_max(BT, &(*phead)->rchild, flag);
330 }
331 
332 static void tree_pre_traverse(BTree *BT, BTNode *phead)
333 {//先序遍历二叉树
334     if(phead == NULL)
335         return;
336 
337     BT->print(BT, phead);
338     if(phead->lchild != NULL)
339         BT->pre_traverse(BT, phead->lchild);
340     if(phead->rchild != NULL)
341         BT->pre_traverse(BT, phead->rchild);
342 }
343 
344 static void tree_mid_traverse(BTree *BT, BTNode *phead)
345 {//中序遍历二叉树
346     if(phead == NULL)
347         return;
348 
349     if(phead->lchild != NULL)
350         BT->mid_traverse(BT, phead->lchild);
351     BT->print(BT, phead);
352     if(phead->rchild != NULL)
353         BT->mid_traverse(BT, phead->rchild);
354 }
355 
356 static void tree_last_traverse(BTree *BT, BTNode *phead)
357 {//后序遍历二叉树
358     if(phead == NULL)
359         return;
360 
361     if(phead->lchild != NULL)
362         BT->last_traverse(BT, phead->lchild);
363     if(phead->rchild != NULL)
364         BT->last_traverse(BT, phead->rchild);
365     BT->print(BT, phead);
366 }
367 
368 static int tree_node_height(BTree *BT, BTNode *phead)
369 {//求节点的高度,写成函数解决指针为空的情况,默认空节点的高度为-1,只有一个根节点的节点的高度为0,每多一层高度加1
370     if(phead != NULL){
371         if(phead->lchild == NULL && phead->rchild == NULL){
372             return 0;
373         }
374         else{
375             return phead->height = max_height(tree_node_height(BT, phead->lchild), tree_node_height(BT, phead->rchild)) + 1;
376         }
377     }
378     else{
379         return -1;
380     }
381 }
382 
383 static void tree_height(BTree *BT, BTNode *phead)
384 {//遍历求树中每个节点的高度
385     if(phead == NULL)
386         return;
387 
388     tree_node_height(BT, phead);
389     if(phead->lchild != NULL)
390         tree_node_height(BT, phead->lchild);
391     if(phead->rchild != NULL)
392         tree_node_height(BT, phead->rchild);
393 }
394 
395 static int max_height(int height1, int height2)
396 {//求两个高度的最大值
397     if(height1 > height2)
398         return height1;
399     else
400         return height2;
401 }
402 
403 static BTNode *singleRotateLL(BTree *BT, BTNode *phead)
404 {//不平衡情况为左左的单旋转操作
405     BTNode *temp;
406 
407     if(phead == NULL)
408         return 0;
409 
410     temp = phead->lchild;
411     
412     if(temp->rchild != NULL){
413         phead->lchild = temp->rchild;
414         phead->lchild->height = tree_node_height(BT, phead->lchild);
415     }
416     else
417         phead->lchild = NULL;
418 
419     temp->rchild = phead;
420     if(temp->rchild->data == BT->phead->data){
421         BT->phead = temp;
422     }
423     phead = temp;
424     temp->rchild->height = tree_node_height(BT, temp->rchild);
425     temp->height = tree_node_height(BT, temp);
426     phead->height = tree_node_height(BT, phead);
427     
428     return phead;
429 }
430 
431 static BTNode *singleRotateRR(BTree *BT, BTNode *phead)
432 {//不平衡情况为右右的单旋转操作
433     BTNode *temp;
434 
435     if(phead == NULL)
436         return 0;
437 
438     temp = phead->rchild;
439 
440     if(temp->lchild != NULL){
441         phead->rchild = temp->lchild;
442         phead->rchild->height = tree_node_height(BT, phead->rchild);
443     }
444     else
445         phead->rchild = NULL;
446 
447     temp->lchild = phead;
448     if(temp->lchild->data == BT->phead->data){
449         BT->phead = temp;
450     }
451     phead = temp;
452     temp->lchild->height = tree_node_height(BT, temp->lchild);
453     temp->height = tree_node_height(BT, temp);
454     phead->height = tree_node_height(BT, phead);
455 
456     return phead;
457 }
458 static BTNode *doubleRotateLR(BTree *BT, BTNode *phead)
459 {//不平衡情况为左右的双旋转操作
460     BTNode *temp;
461 
462     if(phead == NULL)
463         return 0;
464 
465     temp = phead->lchild;    
466     phead->lchild = singleRotateRR(BT, temp);
467     temp = phead;
468     phead = singleRotateLL(BT, temp);
469 
470     return phead;
471 }
472 
473 static BTNode *doubleRotateRL(BTree *BT, BTNode *phead)
474 {//不平衡情况为右左的双旋转操作
475     BTNode *temp;
476 
477     if(phead == NULL)
478         return 0;
479 
480     temp = phead->rchild;
481     phead->rchild = singleRotateLL(BT, temp);
482     temp = phead;
483     phead = singleRotateRR(BT, temp);
484 
485     return phead;
486 }
487 
488 int main(int argc, char* argv[])
489 {//测试
490     BTree testtree;
491     testtree.init = tree_init;
492     testtree.init(&testtree, 9);
493 
494     testtree.add(&testtree, testtree.phead, 4);
495     testtree.add(&testtree, testtree.phead, 5);
496     testtree.add(&testtree, testtree.phead, 6);
497     testtree.add(&testtree, testtree.phead, 1);
498     testtree.add(&testtree, testtree.phead, 7);
499     testtree.add(&testtree, testtree.phead, 8);
500     testtree.add(&testtree, testtree.phead, 11);
501     testtree.add(&testtree, testtree.phead, 10);
502 
503     testtree.pre_traverse(&testtree, testtree.phead);
504     printf("\n");
505     testtree.mid_traverse(&testtree, testtree.phead);
506     printf("\n");
507     testtree.last_traverse(&testtree, testtree.phead);
508     printf("\n");
509 
510     printf("%d\n", (testtree.search(&testtree, testtree.phead, 8))->data);
511     printf("\n");
512 
513     testtree.del(&testtree, &testtree.phead, 4);
514     testtree.del(&testtree, &testtree.phead, 1);
515     testtree.del(&testtree, &testtree.phead, 6);
516     testtree.alter(&testtree, testtree.phead, 9, 2);
517 
518     testtree.pre_traverse(&testtree, testtree.phead);
519     printf("\n");
520     testtree.mid_traverse(&testtree, testtree.phead);
521     printf("\n");
522     testtree.last_traverse(&testtree, testtree.phead);
523     printf("\n");
524 
525     return 0;
526 }

View Code

 

欢迎转载,请备注原始连接http://www.cnblogs.com/liuliuliu/p/3941748.html,并注明转载。

作者bibibi_liuliu,联系方式395985239@qq.com

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/liuliuliu/p/3941748.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞