Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6d81682

Browse files
committed
Tree: add tree source code.
1 parent dda21e8 commit 6d81682

30 files changed

+6934
-0
lines changed

source/tree/avl_tree/c/avltree.c

Lines changed: 395 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,395 @@
1+
/**
2+
* AVL树(C语言): C语言实现的AVL树。
3+
*
4+
* @author skywang
5+
* @date 2013/11/07
6+
*/
7+
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include "avltree.h"
11+
12+
#define HEIGHT(p) ( (p==NULL) ? 0 : (((Node *)(p))->height) )
13+
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
14+
15+
/*
16+
* 获取AVL树的高度
17+
*/
18+
int avltree_height(AVLTree tree)
19+
{
20+
return HEIGHT(tree);
21+
}
22+
23+
/*
24+
* 前序遍历"AVL树"
25+
*/
26+
void preorder_avltree(AVLTree tree)
27+
{
28+
if(tree != NULL)
29+
{
30+
printf("%d ", tree->key);
31+
preorder_avltree(tree->left);
32+
preorder_avltree(tree->right);
33+
}
34+
}
35+
36+
37+
/*
38+
* 中序遍历"AVL树"
39+
*/
40+
void inorder_avltree(AVLTree tree)
41+
{
42+
if(tree != NULL)
43+
{
44+
inorder_avltree(tree->left);
45+
printf("%d ", tree->key);
46+
inorder_avltree(tree->right);
47+
}
48+
}
49+
50+
/*
51+
* 后序遍历"AVL树"
52+
*/
53+
void postorder_avltree(AVLTree tree)
54+
{
55+
if(tree != NULL)
56+
{
57+
postorder_avltree(tree->left);
58+
postorder_avltree(tree->right);
59+
printf("%d ", tree->key);
60+
}
61+
}
62+
63+
/*
64+
* (递归实现)查找"AVL树x"中键值为key的节点
65+
*/
66+
Node* avltree_search(AVLTree x, Type key)
67+
{
68+
if (x==NULL || x->key==key)
69+
return x;
70+
71+
if (key < x->key)
72+
return avltree_search(x->left, key);
73+
else
74+
return avltree_search(x->right, key);
75+
}
76+
77+
/*
78+
* (非递归实现)查找"AVL树x"中键值为key的节点
79+
*/
80+
Node* iterative_avltree_search(AVLTree x, Type key)
81+
{
82+
while ((x!=NULL) && (x->key!=key))
83+
{
84+
if (key < x->key)
85+
x = x->left;
86+
else
87+
x = x->right;
88+
}
89+
90+
return x;
91+
}
92+
93+
/*
94+
* 查找最小结点:返回tree为根结点的AVL树的最小结点。
95+
*/
96+
Node* avltree_minimum(AVLTree tree)
97+
{
98+
if (tree == NULL)
99+
return NULL;
100+
101+
while(tree->left != NULL)
102+
tree = tree->left;
103+
return tree;
104+
}
105+
106+
/*
107+
* 查找最大结点:返回tree为根结点的AVL树的最大结点。
108+
*/
109+
Node* avltree_maximum(AVLTree tree)
110+
{
111+
if (tree == NULL)
112+
return NULL;
113+
114+
while(tree->right != NULL)
115+
tree = tree->right;
116+
return tree;
117+
}
118+
119+
/*
120+
* LL:左左对应的情况(左单旋转)。
121+
*
122+
* 返回值:旋转后的根节点
123+
*/
124+
static Node* left_left_rotation(AVLTree k2)
125+
{
126+
AVLTree k1;
127+
128+
k1 = k2->left;
129+
k2->left = k1->right;
130+
k1->right = k2;
131+
132+
k2->height = MAX( HEIGHT(k2->left), HEIGHT(k2->right)) + 1;
133+
k1->height = MAX( HEIGHT(k1->left), k2->height) + 1;
134+
135+
return k1;
136+
}
137+
138+
/*
139+
* RR:右右对应的情况(右单旋转)。
140+
*
141+
* 返回值:旋转后的根节点
142+
*/
143+
static Node* right_right_rotation(AVLTree k1)
144+
{
145+
AVLTree k2;
146+
147+
k2 = k1->right;
148+
k1->right = k2->left;
149+
k2->left = k1;
150+
151+
k1->height = MAX( HEIGHT(k1->left), HEIGHT(k1->right)) + 1;
152+
k2->height = MAX( HEIGHT(k2->right), k1->height) + 1;
153+
154+
return k2;
155+
}
156+
157+
/*
158+
* LR:左右对应的情况(左双旋转)。
159+
*
160+
* 返回值:旋转后的根节点
161+
*/
162+
static Node* left_right_rotation(AVLTree k3)
163+
{
164+
k3->left = right_right_rotation(k3->left);
165+
166+
return left_left_rotation(k3);
167+
}
168+
169+
/*
170+
* RL:右左对应的情况(右双旋转)。
171+
*
172+
* 返回值:旋转后的根节点
173+
*/
174+
static Node* right_left_rotation(AVLTree k1)
175+
{
176+
k1->right = left_left_rotation(k1->right);
177+
178+
return right_right_rotation(k1);
179+
}
180+
181+
/*
182+
* 创建AVL树结点。
183+
*
184+
* 参数说明:
185+
* key 是键值。
186+
* left 是左孩子。
187+
* right 是右孩子。
188+
*/
189+
static Node* avltree_create_node(Type key, Node *left, Node* right)
190+
{
191+
Node* p;
192+
193+
if ((p = (Node *)malloc(sizeof(Node))) == NULL)
194+
return NULL;
195+
p->key = key;
196+
p->height = 0;
197+
p->left = left;
198+
p->right = right;
199+
200+
return p;
201+
}
202+
203+
/*
204+
* 将结点插入到AVL树中,并返回根节点
205+
*
206+
* 参数说明:
207+
* tree AVL树的根结点
208+
* key 插入的结点的键值
209+
* 返回值:
210+
* 根节点
211+
*/
212+
Node* avltree_insert(AVLTree tree, Type key)
213+
{
214+
if (tree == NULL)
215+
{
216+
// 新建节点
217+
tree = avltree_create_node(key, NULL, NULL);
218+
if (tree==NULL)
219+
{
220+
printf("ERROR: create avltree node failed!\n");
221+
return NULL;
222+
}
223+
}
224+
else if (key < tree->key) // 应该将key插入到"tree的左子树"的情况
225+
{
226+
tree->left = avltree_insert(tree->left, key);
227+
// 插入节点后,若AVL树失去平衡,则进行相应的调节。
228+
if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
229+
{
230+
if (key < tree->left->key)
231+
tree = left_left_rotation(tree);
232+
else
233+
tree = left_right_rotation(tree);
234+
}
235+
}
236+
else if (key > tree->key) // 应该将key插入到"tree的右子树"的情况
237+
{
238+
tree->right = avltree_insert(tree->right, key);
239+
// 插入节点后,若AVL树失去平衡,则进行相应的调节。
240+
if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
241+
{
242+
if (key > tree->right->key)
243+
tree = right_right_rotation(tree);
244+
else
245+
tree = right_left_rotation(tree);
246+
}
247+
}
248+
else //key == tree->key)
249+
{
250+
printf("添加失败:不允许添加相同的节点!\n");
251+
}
252+
253+
tree->height = MAX( HEIGHT(tree->left), HEIGHT(tree->right)) + 1;
254+
255+
return tree;
256+
}
257+
258+
/*
259+
* 删除结点(z),返回根节点
260+
*
261+
* 参数说明:
262+
* ptree AVL树的根结点
263+
* z 待删除的结点
264+
* 返回值:
265+
* 根节点
266+
*/
267+
static Node* delete_node(AVLTree tree, Node *z)
268+
{
269+
// 根为空 或者 没有要删除的节点,直接返回NULL。
270+
if (tree==NULL || z==NULL)
271+
return NULL;
272+
273+
if (z->key < tree->key) // 待删除的节点在"tree的左子树"中
274+
{
275+
tree->left = delete_node(tree->left, z);
276+
// 删除节点后,若AVL树失去平衡,则进行相应的调节。
277+
if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
278+
{
279+
Node *r = tree->right;
280+
if (HEIGHT(r->left) > HEIGHT(r->right))
281+
tree = right_left_rotation(tree);
282+
else
283+
tree = right_right_rotation(tree);
284+
}
285+
}
286+
else if (z->key > tree->key)// 待删除的节点在"tree的右子树"中
287+
{
288+
tree->right = delete_node(tree->right, z);
289+
// 删除节点后,若AVL树失去平衡,则进行相应的调节。
290+
if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
291+
{
292+
Node *l = tree->left;
293+
if (HEIGHT(l->right) > HEIGHT(l->left))
294+
tree = left_right_rotation(tree);
295+
else
296+
tree = left_left_rotation(tree);
297+
}
298+
}
299+
else // tree是对应要删除的节点。
300+
{
301+
// tree的左右孩子都非空
302+
if ((tree->left) && (tree->right))
303+
{
304+
if (HEIGHT(tree->left) > HEIGHT(tree->right))
305+
{
306+
// 如果tree的左子树比右子树高;
307+
// 则(01)找出tree的左子树中的最大节点
308+
// (02)将该最大节点的值赋值给tree。
309+
// (03)删除该最大节点。
310+
// 这类似于用"tree的左子树中最大节点"做"tree"的替身;
311+
// 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
312+
Node *max = avltree_maximum(tree->left);
313+
tree->key = max->key;
314+
tree->left = delete_node(tree->left, max);
315+
}
316+
else
317+
{
318+
// 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
319+
// 则(01)找出tree的右子树中的最小节点
320+
// (02)将该最小节点的值赋值给tree。
321+
// (03)删除该最小节点。
322+
// 这类似于用"tree的右子树中最小节点"做"tree"的替身;
323+
// 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
324+
Node *min = avltree_maximum(tree->right);
325+
tree->key = min->key;
326+
tree->right = delete_node(tree->right, min);
327+
}
328+
}
329+
else
330+
{
331+
Node *tmp = tree;
332+
tree = tree->left ? tree->left : tree->right;
333+
free(tmp);
334+
}
335+
}
336+
337+
return tree;
338+
}
339+
340+
/*
341+
* 删除结点(key是节点值),返回根节点
342+
*
343+
* 参数说明:
344+
* tree AVL树的根结点
345+
* key 待删除的结点的键值
346+
* 返回值:
347+
* 根节点
348+
*/
349+
Node* avltree_delete(AVLTree tree, Type key)
350+
{
351+
Node *z;
352+
353+
if ((z = avltree_search(tree, key)) != NULL)
354+
tree = delete_node(tree, z);
355+
return tree;
356+
}
357+
358+
/*
359+
* 销毁AVL树
360+
*/
361+
void destroy_avltree(AVLTree tree)
362+
{
363+
if (tree==NULL)
364+
return ;
365+
366+
if (tree->left != NULL)
367+
destroy_avltree(tree->left);
368+
if (tree->right != NULL)
369+
destroy_avltree(tree->right);
370+
371+
free(tree);
372+
}
373+
374+
/*
375+
* 打印"AVL树"
376+
*
377+
* tree -- AVL树的节点
378+
* key -- 节点的键值
379+
* direction -- 0,表示该节点是根节点;
380+
* -1,表示该节点是它的父结点的左孩子;
381+
* 1,表示该节点是它的父结点的右孩子。
382+
*/
383+
void print_avltree(AVLTree tree, Type key, int direction)
384+
{
385+
if(tree != NULL)
386+
{
387+
if(direction==0) // tree是根节点
388+
printf("%2d is root\n", tree->key, key);
389+
else // tree是分支节点
390+
printf("%2d is %2d's %6s child\n", tree->key, key, direction==1?"right" : "left");
391+
392+
print_avltree(tree->left, tree->key, -1);
393+
print_avltree(tree->right,tree->key, 1);
394+
}
395+
}

0 commit comments

Comments
 (0)