-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAVL.c
250 lines (231 loc) · 5.87 KB
/
AVL.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
/*
AVL树,建立在二叉查找树的基础上。区别在于利用旋转获得了自平衡性。从而
避免了二叉查找树的退化,将搜索算法时间复杂度稳定在O(logn)。但是也是由
于旋转,在增、删过程中非常复杂,由于递归,可能存在多重旋转。所以在实
际应用上要少于红黑树。但是逻辑比红黑树简单的多。
*/
#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct AVLTree {
ElemType data;
int times; // 使用懒惰增删,即使用times储存该数据的出现次数
int height;
struct TreeNode *Left;
struct TreeNode *Right;
}TreeNode, *Root;
int Max(int a, int b) {
return a > b ? a : b;
}
// 初始化一个空的AVL树
void InitAVLTree(Root *root) {
*root = (Root)malloc(sizeof(TreeNode));
if (!(*root)) {
exit(0);
}
(*root)->times = 0;
(*root)->height = 0;
(*root)->data = NULL;
(*root)->Left = NULL;
(*root)->Right = NULL;
}
void DestroyTree(Root root) {
root->Left = NULL;
root->Right = NULL;
free(root);
}
void MakeEmpty(Root root) {
InitAVLTree(&root);
}
// 判断AVL树是否为空,空则返回1,否则返回0
int isEmpty(Root root) {
if (root->data) {
return 0;
}else {
return 1;
}
}
// 返回数的高,这里定义根的高为1(有的文献定义根为0)
int getHeight(Root root) {
if (root) {
return root->height;
}else {
return 0;
}
}
// 查找数据
void FindAVLTree(Root root,ElemType data) {
if (isEmpty(root)) {
printf("the search tree is empty\n");
exit(0);
}
if (data - root->data == 0) {
if (root->times == 0) {
printf("sorry,no find it!\n");
}else {
printf("find it!\n");
}
}else {
if (data - root->data > 0) {
if (root->Right == NULL) {
printf("sorry,no find it!\n");
}else {
FindAVLTree(root->Right, data);
}
}else {
if (root->Left == NULL) {
printf("sorry,no find it!\n");
}else {
FindAVLTree(root->Left, data);
}
}
}
}
// 查找整个查找树的最大数据,并返回
ElemType FindAVLTreeMax(Root root) {
if (root->Right == NULL) {
return root->data;
}else {
FindAVLTreeMax(root->Right);
}
}
// 查找整个查找树的最小数据,并返回
ElemType FindAVLTreeMin(Root root) {
if (root->Left == NULL) {
return root->data;
}else {
FindAVLTreeMin(root->Left);
}
}
//AVL树的旋转分为4种,详情自搜,不再赘述
Root left_left_rotation(Root root) {
Root temp = root->Left;
root->Left = temp->Right;
temp->Right = root;
root->height = Max(getHeight(root->Left), getHeight(root->Right))+1;
temp->height = Max(getHeight(temp->Left), root->height) + 1;
return temp;
}
Root right_right_rotation(Root root) {
Root temp = root->Right;
root->Right = temp->Left;
temp->Left = root;
root->height = Max(getHeight(root->Left), getHeight(root->Right)) + 1;
temp->height = Max(getHeight(temp->Left), getHeight(temp->Right)) + 1;
return temp;
}
Root left_right_rotation(Root root) {
root->Left = right_right_rotation(root->Left);
return left_left_rotation(root);
}
Root right_left_rotation(Root root) {
root->Right = left_left_rotation(root->Right);
return right_right_rotation(root);
}
// 插入,必须保证自平衡,具体算法参考书《数据结构与算法分析(C语言)》
Root InsertAVLTree(Root root, ElemType data) {
// 由于是递归判断节点,那么节点不存在就说明该插入了
if (root == NULL) {
root = (Root *)malloc(sizeof(Root));
root->data = data;
root->Left = NULL;
root->Right = NULL;
root->times = 1;
root->height = 1;
}else {
if (root->data) {
// 懒惰插入,times++
if (data - root->data == 0) {
root->times++;
}
if (data - root->data > 0) {
// 递归过程,可以构建一棵树自己演算来理解
root->Right = InsertAVLTree(root->Right, data);
if (getHeight(root->Right) - getHeight(root->Left) == 2) {
// 具体旋转方式的判断算法,自己手写演示即可理解
Root temp = root->Right;
if (data > temp->data) {
root = right_right_rotation(root);
}else {
root = right_left_rotation(root);
}
}
}else {
root->Left = InsertAVLTree(root->Left, data);
if (getHeight(root->Left) - getHeight(root->Right) == 2) {
Root temp = root->Left;
if (data < temp->data) {
root = left_left_rotation(root);
}else {
root = left_right_rotation(root);
}
}
}
}else {
root->data = data;
root->times = 1;
root->height = 1;
}
}
// 每次递归的最后都更新节点的高
root->height = Max(getHeight(root->Left), getHeight(root->Right))+1;
return root;
}
// 由于AVL树的删除不是很重要,并且非常繁琐,推荐使用懒惰删除
void DeleteAVLTree(Root root,ElemType data) {
if (isEmpty(root)) {
printf("the search tree is empty\n");
exit(0);
}
if (data - root->data == 0) {
if (root->times == 0) {
printf("sorry,no find it!\n");
}else {
root->times--;
}
}else {
if (data - root->data > 0) {
if (root->Right == NULL) {
printf("sorry,no find it!\n");
}else {
DeleteAVLTree(root->Right, data);
}
}else {
if (root->Left == NULL) {
printf("sorry,no find it!\n");
}else {
DeleteAVLTree(root->Left, data);
}
}
}
}
/*
给出4种旋转的测试数据,修改insert函数的data参数
LL:8 4 12 2 6 1
LR:8 4 12 2 6 5
RL:8 4 12 10 14 9
RR:8 4 12 10 14 13
*/
int main() {
Root avl_tree;
InitAVLTree(&avl_tree);
if (isEmpty(avl_tree)) {
printf("is a empty!\n");
}else {
printf("is not empty!\n");
}
avl_tree = InsertAVLTree(avl_tree, 8);
avl_tree = InsertAVLTree(avl_tree, 12);
avl_tree = InsertAVLTree(avl_tree, 4);
avl_tree = InsertAVLTree(avl_tree, 10);
avl_tree = InsertAVLTree(avl_tree, 14);
avl_tree = InsertAVLTree(avl_tree, 13);
printf("%d\n", FindAVLTreeMax(avl_tree));
printf("%d\n", FindAVLTreeMin(avl_tree));
FindAVLTree(avl_tree, 13);
DeleteAVLTree(avl_tree, 2);
FindAVLTree(avl_tree, 2);
system("pause");
return 0;
}