]> arthur.barton.de Git - netdata.git/blob - src/avl.c
layout: remove executable from unrelated files
[netdata.git] / src / avl.c
1 /*
2  * ANSI C Library for maintainance of AVL Balanced Trees
3  *
4  * ref.:
5  *  G. M. Adelson-Velskij & E. M. Landis
6  *  Doklady Akad. Nauk SSSR 146 (1962), 263-266
7  *
8  * see also:
9  *  D. E. Knuth: The Art of Computer Programming Vol.3 (Sorting and Searching)
10  *
11  * (C) 2000 Daniel Nagy, Budapest University of Technology and Economics
12  * Released under GNU General Public License (GPL) version 2
13  *
14  */
15
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19 #include "avl.h"
20 #include "log.h"
21
22 /* Private methods */
23 int _avl_removeroot(avl_tree* t);
24
25 /* Swing to the left
26  * Warning: no balance maintainance
27  */
28 void avl_swl(avl** root) {
29         avl* a = *root;
30         avl* b = a->right;
31         *root = b;
32         a->right = b->left;
33         b->left = a;
34 }
35
36 /* Swing to the right
37  * Warning: no balance maintainance
38  */
39 void avl_swr(avl** root) {
40         avl* a = *root;
41         avl* b = a->left;
42         *root = b;
43         a->left = b->right;
44         b->right = a;
45 }
46
47 /* Balance maintainance after especially nasty swings
48  */
49 void avl_nasty(avl* root) {
50         switch (root->balance) {
51         case -1:
52                 root->left->balance = 0;
53                 root->right->balance = 1;
54                 break;
55         case 1:
56                 root->left->balance = -1;
57                 root->right->balance = 0;
58                 break;
59         case 0:
60                 root->left->balance = 0;
61                 root->right->balance = 0;
62         }
63         root->balance = 0;
64 }
65
66 /* Public methods */
67
68 /* Insert element a into the AVL tree t
69  * returns 1 if the depth of the tree has grown
70  * Warning: do not insert elements already present
71  */
72 int _avl_insert(avl_tree* t, avl* a) {
73         /* initialize */
74         a->left = 0;
75         a->right = 0;
76         a->balance = 0;
77         /* insert into an empty tree */
78         if (!t->root) {
79                 t->root = a;
80                 return 1;
81         }
82
83         if (t->compar(t->root, a) > 0) {
84                 /* insert into the left subtree */
85                 if (t->root->left) {
86                         avl_tree left_subtree;
87                         left_subtree.root = t->root->left;
88                         left_subtree.compar = t->compar;
89                         if (_avl_insert(&left_subtree, a)) {
90                                 switch (t->root->balance--) {
91                                 case 1:
92                                         return 0;
93                                 case 0:
94                                         return 1;
95                                 }
96                                 if (t->root->left->balance < 0) {
97                                         avl_swr(&(t->root));
98                                         t->root->balance = 0;
99                                         t->root->right->balance = 0;
100                                 } else {
101                                         avl_swl(&(t->root->left));
102                                         avl_swr(&(t->root));
103                                         avl_nasty(t->root);
104                                 }
105                         } else
106                                 t->root->left = left_subtree.root;
107                         return 0;
108                 } else {
109                         t->root->left = a;
110                         if (t->root->balance--)
111                                 return 0;
112                         return 1;
113                 }
114         } else {
115                 /* insert into the right subtree */
116                 if (t->root->right) {
117                         avl_tree right_subtree;
118                         right_subtree.root = t->root->right;
119                         right_subtree.compar = t->compar;
120                         if (_avl_insert(&right_subtree, a)) {
121                                 switch (t->root->balance++) {
122                                 case -1:
123                                         return 0;
124                                 case 0:
125                                         return 1;
126                                 }
127                                 if (t->root->right->balance > 0) {
128                                         avl_swl(&(t->root));
129                                         t->root->balance = 0;
130                                         t->root->left->balance = 0;
131                                 } else {
132                                         avl_swr(&(t->root->right));
133                                         avl_swl(&(t->root));
134                                         avl_nasty(t->root);
135                                 }
136                         } else
137                                 t->root->right = right_subtree.root;
138                         return 0;
139                 } else {
140                         t->root->right = a;
141                         if (t->root->balance++)
142                                 return 0;
143                         return 1;
144                 }
145         }
146 }
147 int avl_insert(avl_tree* t, avl* a) {
148 #ifdef AVL_LOCK_WITH_MUTEX
149         pthread_mutex_lock(&t->mutex);
150 #else
151         pthread_rwlock_wrlock(&t->rwlock);
152 #endif
153
154         int ret = _avl_insert(t, a);
155
156 #ifdef AVL_LOCK_WITH_MUTEX
157         pthread_mutex_unlock(&t->mutex);
158 #else
159         pthread_rwlock_unlock(&t->rwlock);
160 #endif
161         return ret;
162 }
163
164 /* Remove an element a from the AVL tree t
165  * returns -1 if the depth of the tree has shrunk
166  * Warning: if the element is not present in the tree,
167  *          returns 0 as if it had been removed succesfully.
168  */
169 int _avl_remove(avl_tree* t, avl* a) {
170         int b;
171         if (t->root == a)
172                 return _avl_removeroot(t);
173         b = t->compar(t->root, a);
174         if (b >= 0) {
175                 /* remove from the left subtree */
176                 int ch;
177                 avl_tree left_subtree;
178                 if ((left_subtree.root = t->root->left)) {
179                         left_subtree.compar = t->compar;
180                         ch = _avl_remove(&left_subtree, a);
181                         t->root->left = left_subtree.root;
182                         if (ch) {
183                                 switch (t->root->balance++) {
184                                 case -1:
185                                         return -1;
186                                 case 0:
187                                         return 0;
188                                 }
189                                 switch (t->root->right->balance) {
190                                 case 0:
191                                         avl_swl(&(t->root));
192                                         t->root->balance = -1;
193                                         t->root->left->balance = 1;
194                                         return 0;
195                                 case 1:
196                                         avl_swl(&(t->root));
197                                         t->root->balance = 0;
198                                         t->root->left->balance = 0;
199                                         return -1;
200                                 }
201                                 avl_swr(&(t->root->right));
202                                 avl_swl(&(t->root));
203                                 avl_nasty(t->root);
204                                 return -1;
205                         }
206                 }
207         }
208         if (b <= 0) {
209                 /* remove from the right subtree */
210                 int ch;
211                 avl_tree right_subtree;
212                 if ((right_subtree.root = t->root->right)) {
213                         right_subtree.compar = t->compar;
214                         ch = _avl_remove(&right_subtree, a);
215                         t->root->right = right_subtree.root;
216                         if (ch) {
217                                 switch (t->root->balance--) {
218                                 case 1:
219                                         return -1;
220                                 case 0:
221                                         return 0;
222                                 }
223                                 switch (t->root->left->balance) {
224                                 case 0:
225                                         avl_swr(&(t->root));
226                                         t->root->balance = 1;
227                                         t->root->right->balance = -1;
228                                         return 0;
229                                 case -1:
230                                         avl_swr(&(t->root));
231                                         t->root->balance = 0;
232                                         t->root->right->balance = 0;
233                                         return -1;
234                                 }
235                                 avl_swl(&(t->root->left));
236                                 avl_swr(&(t->root));
237                                 avl_nasty(t->root);
238                                 return -1;
239                         }
240                 }
241         }
242         return 0;
243 }
244
245 int avl_remove(avl_tree* t, avl* a) {
246 #ifdef AVL_LOCK_WITH_MUTEX
247         pthread_mutex_lock(&t->mutex);
248 #else
249         pthread_rwlock_wrlock(&t->rwlock);
250 #endif
251
252         int ret = _avl_remove(t, a);
253
254 #ifdef AVL_LOCK_WITH_MUTEX
255         pthread_mutex_unlock(&t->mutex);
256 #else
257         pthread_rwlock_unlock(&t->rwlock);
258 #endif
259         return ret;
260 }
261
262 /* Remove the root of the AVL tree t
263  * Warning: dumps core if t is empty
264  */
265 int _avl_removeroot(avl_tree* t) {
266         int ch;
267         avl* a;
268         if (!t->root->left) {
269                 if (!t->root->right) {
270                         t->root = 0;
271                         return -1;
272                 }
273                 t->root = t->root->right;
274                 return -1;
275         }
276         if (!t->root->right) {
277                 t->root = t->root->left;
278                 return -1;
279         }
280         if (t->root->balance < 0) {
281                 /* remove from the left subtree */
282                 a = t->root->left;
283                 while (a->right)
284                         a = a->right;
285         } else {
286                 /* remove from the right subtree */
287                 a = t->root->right;
288                 while (a->left)
289                         a = a->left;
290         }
291         ch = _avl_remove(t, a);
292         a->left = t->root->left;
293         a->right = t->root->right;
294         a->balance = t->root->balance;
295         t->root = a;
296         if (a->balance == 0)
297                 return ch;
298         return 0;
299 }
300
301 int avl_removeroot(avl_tree* t) {
302 #ifdef AVL_LOCK_WITH_MUTEX
303         pthread_mutex_lock(&t->mutex);
304 #else
305         pthread_rwlock_wrlock(&t->rwlock);
306 #endif
307
308         int ret = _avl_removeroot(t);
309
310 #ifdef AVL_LOCK_WITH_MUTEX
311         pthread_mutex_unlock(&t->mutex);
312 #else
313         pthread_rwlock_unlock(&t->rwlock);
314 #endif
315         return ret;
316 }
317
318 /* Iterate through elements in t from a range between a and b (inclusive)
319  * for each element calls iter(a) until it returns 0
320  * returns the last value returned by iterator or 0 if there were no calls
321  * Warning: a<=b must hold
322  */
323 int _avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl*), avl** ret) {
324         int x, c = 0;
325         if (!t->root)
326                 return 0;
327         x = t->compar(t->root, a);
328         if (a != b) {
329                 if (x < 0) {
330                         x = t->compar(t->root, b);
331                         if (x > 0)
332                                 x = 0;
333                 }
334         }
335         if (x >= 0) {
336                 /* search in the left subtree */
337                 avl_tree left_subtree;
338                 if ((left_subtree.root = t->root->left)) {
339                         left_subtree.compar = t->compar;
340                         if (!(c = _avl_range(&left_subtree, a, b, iter, ret)))
341                                 if (x > 0)
342                                         return 0;
343                 }
344         }
345         if (x == 0) {
346                 if (!(c = iter(t->root))) {
347                         if (ret)
348                                 *ret = t->root;
349                         return 0;
350                 }
351         }
352         if (x <= 0) {
353                 /* search in the right subtree */
354                 avl_tree right_subtree;
355                 if ((right_subtree.root = t->root->right)) {
356                         right_subtree.compar = t->compar;
357                         if (!(c = _avl_range(&right_subtree, a, b, iter, ret)))
358                                 if (x < 0)
359                                         return 0;
360                 }
361         }
362         return c;
363 }
364
365 int avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl*), avl** ret) {
366 #ifdef AVL_LOCK_WITH_MUTEX
367         pthread_mutex_lock(&t->mutex);
368 #else
369         pthread_rwlock_wrlock(&t->rwlock);
370 #endif
371
372         int ret2 = _avl_range(t, a, b, iter, ret);
373
374 #ifdef AVL_LOCK_WITH_MUTEX
375         pthread_mutex_unlock(&t->mutex);
376 #else
377         pthread_rwlock_unlock(&t->rwlock);
378 #endif
379
380         return ret2;
381 }
382
383 /* Iterate through elements in t equal to a
384  * for each element calls iter(a) until it returns 0
385  * returns the last value returned by iterator or 0 if there were no calls
386  */
387 int avl_search(avl_tree* t, avl* a, int (*iter)(avl* a), avl** ret) {
388         return avl_range(t, a, a, iter, ret);
389 }
390
391 void avl_init(avl_tree* t, int (*compar)(void* a, void* b)) {
392         t->root = NULL;
393         t->compar = compar;
394
395         int lock;
396 #ifdef AVL_LOCK_WITH_MUTEX
397         lock = pthread_mutex_init(&t->mutex, NULL);
398 #else
399         lock = pthread_rwlock_init(&t->rwlock, NULL);
400 #endif
401
402         if(lock != 0)
403                 fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
404 }