Code

3665760bca88b1f5f1b2f871f1ebb64d0863a862
[collectd.git] / src / utils_avltree.c
1 #include <stdlib.h>
2 #include <assert.h>
4 #include "utils_avltree.h"
6 #define BALANCE(n) ((((n)->right == NULL) ? 0 : (n)->right->height) \
7                                  - (((n)->left == NULL) ? 0 : (n)->left->height))
9 /*
10  * private data types
11  */
12 struct avl_node_s
13 {
14         void *key;
15         void *value;
17         int height;
18         struct avl_node_s *left;
19         struct avl_node_s *right;
20         struct avl_node_s *parent;
21 };
22 typedef struct avl_node_s avl_node_t;
24 struct avl_tree_s
25 {
26         avl_node_t *root;
27         int (*compare) (const void *, const void *);
28 };
30 struct avl_iterator_s
31 {
32         avl_tree_t *tree;
33         avl_node_t *node;
34 };
36 /*
37  * private functions
38  */
39 static void free_node (avl_node_t *n)
40 {
41         if (n == NULL)
42                 return;
44         if (n->left != NULL)
45                 free_node (n->left);
46         if (n->right != NULL)
47                 free_node (n->right);
49         free (n);
50 }
52 static avl_node_t *search (avl_tree_t *t, void *key)
53 {
54         avl_node_t *n;
55         int cmp;
57         n = t->root;
58         while (n != NULL)
59         {
60                 cmp = t->compare (key, n->key);
61                 if (cmp == 0)
62                         return (n);
63                 else if (cmp < 0)
64                         n = n->left;
65                 else
66                         n = n->right;
67         }
69         return (NULL);
70 }
72 static void rebalance (avl_tree_t *t, avl_node_t *n)
73 {
74         int height_left;
75         int height_right;
76         int height_new;
77         int cmp;
79         while (n != NULL)
80         {
81                 height_left = (n->left == NULL) ? 0 : n->left->height;
82                 height_right = (n->right == NULL) ? 0 : n->right->height;
84                 height_new = 1 + ((height_left > height_right) ? height_left : height_right);
86                 if (height_new == n->height)
87                         break;
89                 n->height = height_new;
91                 cmp = height_right - height_left;
92                 if (cmp < -1)
93                 {
94                         avl_node_t *l;
95                         avl_node_t *lr;
97                         l = n->left;
98                         lr = l->right;
100                         l->right = n;
101                         l->parent = n->parent;
102                         n->parent = l;
103                         n->left = lr;
105                         if (lr != NULL)
106                                 lr->parent = n;
108                         if (l->parent == NULL)
109                         {
110                                 assert (t->root == n);
111                                 t->root = l;
112                         }
113                         else
114                         {
115                                 assert ((l->parent->left == n) || (l->parent->right == n));
116                                 if (l->parent->left == n)
117                                         l->parent->left = l;
118                                 else
119                                         l->parent->right = l;
120                         }
121                 }
122                 else if (cmp > 1)
123                 {
124                         avl_node_t *r;
125                         avl_node_t *rl;
127                         r = n->right;
128                         rl = r->left;
130                         r->left = n;
131                         r->parent = n->parent;
132                         n->parent = r;
133                         n->right = rl;
135                         if (rl != NULL)
136                                 rl->parent = n;
138                         if (r->parent == NULL)
139                         {
140                                 assert (t->root == n);
141                                 t->root = r;
142                         }
143                         else
144                         {
145                                 assert ((r->parent->left == n) || (r->parent->right == n));
146                                 if (r->parent->left == n)
147                                         r->parent->left = r;
148                                 else
149                                         r->parent->right = r;
150                         }
151                 }
152                 else
153                 {
154                         n = n->parent;
155                 }
157                 assert ((n == NULL) || (n->parent == NULL)
158                                 || (n->parent->left == n)
159                                 || (n->parent->right == n));
160         } /* while (n != NULL) */
161 } /* void rebalance */
163 static avl_iterator_t *avl_create_iterator (avl_tree_t *t, avl_node_t *n)
165         avl_iterator_t *iter;
167         iter = (avl_iterator_t *) malloc (sizeof (avl_iterator_t));
168         if (iter == NULL)
169                 return (NULL);
171         iter->tree = t;
172         iter->node = n;
174         return (iter);
177 void *avl_node_next (avl_tree_t *t, avl_node_t *n)
179         avl_node_t *r; /* return node */
181         if (n == NULL)
182         {
183                 return (NULL);
184         }
185         else if (n->right == NULL)
186         {
188                 r = n->parent;
189                 while (r != NULL)
190                 {
191                         /* stop if a bigger node is found */
192                         if (t->compare (n, r) < 0) /* n < r */
193                                 break;
194                         r = r->parent;
195                 }
196         }
197         else
198         {
199                 r = n->right;
200                 while (r->left != NULL)
201                         r = r->left;
202         }
204         return (r);
207 void *avl_node_prev (avl_tree_t *t, avl_node_t *n)
209         avl_node_t *r; /* return node */
211         if (n == NULL)
212         {
213                 return (NULL);
214         }
215         else if (n->left == NULL)
216         {
218                 r = n->parent;
219                 while (r != NULL)
220                 {
221                         /* stop if a smaller node is found */
222                         if (t->compare (n, r) > 0) /* n > r */
223                                 break;
224                         r = r->parent;
225                 }
226         }
227         else
228         {
229                 r = n->left;
230                 while (r->right != NULL)
231                         r = r->right;
232         }
234         return (r);
237 static void *_remove (avl_tree_t *t, avl_node_t *n)
239         void *ret;
241         assert ((t != NULL) && (n != NULL));
243         ret = n->value;
245         if ((n->left == NULL) && (n->right == NULL))
246         {
247                 /* Deleting a leave is easy */
248                 if (n->parent == NULL)
249                 {
250                         assert (t->root == n);
251                         t->root = NULL;
252                 }
253                 else
254                 {
255                         assert ((n->parent->left == n)
256                                         || (n->parent->right == n));
257                         if (n->parent->left == n)
258                                 n->parent->left = NULL;
259                         else
260                                 n->parent->right = NULL;
262                         rebalance (t, n->parent);
263                 }
265                 free_node (n);
266         }
267         else
268         {
269                 avl_node_t *r; /* replacement node */
270                 if (BALANCE (n) < 0)
271                 {
272                         assert (n->left != NULL);
273                         r = avl_node_prev (t, n);
274                 }
275                 else
276                 {
277                         assert (n->right != NULL);
278                         r = avl_node_next (t, n);
279                 }
280                 n->key   = r->key;
281                 n->value = r->value;
283                 _remove (t, r);
284         }
286         return (ret);
287 } /* void *_remove */
289 /*
290  * public functions
291  */
292 avl_tree_t *avl_create (int (*compare) (const void *, const void *))
294         avl_tree_t *t;
296         if ((t = (avl_tree_t *) malloc (sizeof (avl_tree_t))) == NULL)
297                 return (NULL);
299         t->root = NULL;
300         t->compare = compare;
302         return (t);
305 void avl_destroy (avl_tree_t *t)
307         free_node (t->root);
308         free (t);
311 int avl_insert (avl_tree_t *t, void *key, void *value)
313         avl_node_t *new;
314         avl_node_t *nptr;
315         int cmp;
317         if ((new = (avl_node_t *) malloc (sizeof (avl_node_t))) == NULL)
318                 return (-1);
320         new->key = key;
321         new->value = value;
322         new->height = 1;
323         new->left = NULL;
324         new->right = NULL;
326         if (t->root == NULL)
327         {
328                 new->parent = NULL;
329                 t->root = new;
330                 return (0);
331         }
333         nptr = t->root;
334         while (42)
335         {
336                 cmp = t->compare (nptr->key, new->key);
337                 if (cmp == 0)
338                 {
339                         free_node (new);
340                         return (-1);
341                 }
342                 else if (cmp < 0)
343                 {
344                         /* nptr < new */
345                         if (nptr->right == NULL)
346                         {
347                                 nptr->right = new;
348                                 new->parent = nptr;
349                                 nptr = NULL;
350                                 break;
351                         }
352                         else
353                         {
354                                 nptr = nptr->right;
355                         }
356                 }
357                 else /* if (cmp > 0) */
358                 {
359                         /* nptr > new */
360                         if (nptr->left == NULL)
361                         {
362                                 nptr->left = new;
363                                 new->parent = nptr;
364                                 nptr = NULL;
365                                 break;
366                         }
367                         else
368                         {
369                                 nptr = nptr->left;
370                         }
371                 }
372         } /* while (42) */
374         assert ((new->parent != NULL)
375                         && ((new->parent->left == new)
376                                 || (new->parent->right == new)));
378         return (0);
379 } /* int avl_insert */
381 void *avl_remove (avl_tree_t *t, void *key)
383         avl_node_t *n;
385         assert (t != NULL);
387         n = search (t, key);
388         if (n == NULL)
389                 return (NULL);
391         return (_remove (t, n));
392 } /* void *avl_remove */
394 void *avl_get (avl_tree_t *t, void *key)
396         avl_node_t *n;
398         n = search (t, key);
399         if (n == NULL)
400                 return (NULL);
402         return (n->value);
405 avl_iterator_t *avl_get_iterator (avl_tree_t *t)
407         avl_node_t *n;
409         if (t == NULL)
410                 return (NULL);
412         for (n = t->root; n != NULL; n = n->left)
413                 if (n->left == NULL)
414                         break;
416         return (avl_create_iterator (t, n));
417 } /* avl_iterator_t *avl_get_iterator */
419 void *avl_iterator_next (avl_iterator_t *iter)
421         avl_node_t *n;
423         if ((iter == NULL) || (iter->node == NULL))
424                 return (NULL);
426         n = avl_node_next (iter->tree, iter->node);
428         if (n == NULL)
429                 return (NULL);
431         iter->node = n;
432         return (n);
436 void *avl_iterator_prev (avl_iterator_t *iter)
438         avl_node_t *n;
440         if ((iter == NULL) || (iter->node == NULL))
441                 return (NULL);
443         n = avl_node_prev (iter->tree, iter->node);
445         if (n == NULL)
446                 return (NULL);
448         iter->node = n;
449         return (n);
453 void avl_iterator_destroy (avl_iterator_t *iter)
455         free (iter);