X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_avltree.c;h=12310d3fa771d528fabc5ac313f76d42ed71aef6;hb=b4c8f3f762d666742c774ab3b45815e5a416e5da;hp=830b711f8f9713d45bfe5b898995b2ac5f85b7ae;hpb=f4c3e684850315991f0760e90f5d845af4615d5f;p=collectd.git diff --git a/src/utils_avltree.c b/src/utils_avltree.c index 830b711f..12310d3f 100644 --- a/src/utils_avltree.c +++ b/src/utils_avltree.c @@ -19,8 +19,12 @@ * Authors: * Florian octo Forster **/ + +#include "config.h" + #include #include +#include #include #include "utils_avltree.h" @@ -31,35 +35,35 @@ /* * private data types */ -struct avl_node_s +struct c_avl_node_s { void *key; void *value; int height; - struct avl_node_s *left; - struct avl_node_s *right; - struct avl_node_s *parent; + struct c_avl_node_s *left; + struct c_avl_node_s *right; + struct c_avl_node_s *parent; }; -typedef struct avl_node_s avl_node_t; +typedef struct c_avl_node_s c_avl_node_t; -struct avl_tree_s +struct c_avl_tree_s { - avl_node_t *root; + c_avl_node_t *root; int (*compare) (const void *, const void *); }; -struct avl_iterator_s +struct c_avl_iterator_s { - avl_tree_t *tree; - avl_node_t *node; + c_avl_tree_t *tree; + c_avl_node_t *node; }; /* * private functions */ #if 0 -static void verify_tree (avl_node_t *n) +static void verify_tree (c_avl_node_t *n) { if (n == NULL) return; @@ -74,7 +78,7 @@ static void verify_tree (avl_node_t *n) # define verify_tree(n) /**/ #endif -static void free_node (avl_node_t *n) +static void free_node (c_avl_node_t *n) { if (n == NULL) return; @@ -87,7 +91,7 @@ static void free_node (avl_node_t *n) free (n); } -static int calc_height (avl_node_t *n) +static int calc_height (c_avl_node_t *n) { int height_left; int height_right; @@ -103,9 +107,9 @@ static int calc_height (avl_node_t *n) : height_right) + 1); } /* int calc_height */ -static avl_node_t *search (avl_tree_t *t, const void *key) +static c_avl_node_t *search (c_avl_tree_t *t, const void *key) { - avl_node_t *n; + c_avl_node_t *n; int cmp; n = t->root; @@ -131,11 +135,11 @@ static avl_node_t *search (avl_tree_t *t, const void *key) * / a\ /_b\ /_b\ /_c\ * /____\ */ -static avl_node_t *rotate_right (avl_tree_t *t, avl_node_t *x) +static c_avl_node_t *rotate_right (c_avl_tree_t *t, c_avl_node_t *x) { - avl_node_t *p; - avl_node_t *y; - avl_node_t *b; + c_avl_node_t *p; + c_avl_node_t *y; + c_avl_node_t *b; p = x->parent; y = x->left; @@ -172,11 +176,11 @@ static avl_node_t *rotate_right (avl_tree_t *t, avl_node_t *x) * /_b\ / c\ /_a\ /_b\ * /____\ */ -static avl_node_t *rotate_left (avl_tree_t *t, avl_node_t *x) +static c_avl_node_t *rotate_left (c_avl_tree_t *t, c_avl_node_t *x) { - avl_node_t *p; - avl_node_t *y; - avl_node_t *b; + c_avl_node_t *p; + c_avl_node_t *y; + c_avl_node_t *b; p = x->parent; y = x->right; @@ -204,19 +208,19 @@ static avl_node_t *rotate_left (avl_tree_t *t, avl_node_t *x) return (y); } /* void rotate_left */ -static avl_node_t *rotate_left_right (avl_tree_t *t, avl_node_t *x) +static c_avl_node_t *rotate_left_right (c_avl_tree_t *t, c_avl_node_t *x) { rotate_left (t, x->left); return (rotate_right (t, x)); } /* void rotate_left_right */ -static avl_node_t *rotate_right_left (avl_tree_t *t, avl_node_t *x) +static c_avl_node_t *rotate_right_left (c_avl_tree_t *t, c_avl_node_t *x) { rotate_right (t, x->right); return (rotate_left (t, x)); } /* void rotate_right_left */ -static void rebalance (avl_tree_t *t, avl_node_t *n) +static void rebalance (c_avl_tree_t *t, c_avl_node_t *n) { int b_top; int b_bottom; @@ -260,38 +264,39 @@ static void rebalance (avl_tree_t *t, avl_node_t *n) } /* while (n != NULL) */ } /* void rebalance */ -static avl_iterator_t *avl_create_iterator (avl_tree_t *t, avl_node_t *n) +static c_avl_node_t *c_avl_node_next (c_avl_node_t *n) { - avl_iterator_t *iter; - - iter = (avl_iterator_t *) malloc (sizeof (avl_iterator_t)); - if (iter == NULL) - return (NULL); - - iter->tree = t; - iter->node = n; - - return (iter); -} - -void *avl_node_next (avl_tree_t *t, avl_node_t *n) -{ - avl_node_t *r; /* return node */ + c_avl_node_t *r; /* return node */ if (n == NULL) { return (NULL); } - else if (n->right == NULL) - { + /* If we can't descent any further, we have to backtrack to the first + * parent that's bigger than we, i. e. who's _left_ child we are. */ + if (n->right == NULL) + { r = n->parent; - while (r != NULL) + while ((r != NULL) && (r->parent != NULL)) { - /* stop if a bigger node is found */ - if (t->compare (n, r) < 0) /* n < r */ + if (r->left == n) break; - r = r->parent; + n = r; + r = n->parent; + } + + /* n->right == NULL && r == NULL => t is root and has no next + * r->left != n => r->right = n => r->parent == NULL */ + if ((r == NULL) || (r->left != n)) + { + assert ((r == NULL) || (r->parent == NULL)); + return (NULL); + } + else + { + assert (r->left == n); + return (r); } } else @@ -302,26 +307,41 @@ void *avl_node_next (avl_tree_t *t, avl_node_t *n) } return (r); -} +} /* c_avl_node_t *c_avl_node_next */ -void *avl_node_prev (avl_tree_t *t, avl_node_t *n) +static c_avl_node_t *c_avl_node_prev (c_avl_node_t *n) { - avl_node_t *r; /* return node */ + c_avl_node_t *r; /* return node */ if (n == NULL) { return (NULL); } - else if (n->left == NULL) - { + /* If we can't descent any further, we have to backtrack to the first + * parent that's smaller than we, i. e. who's _right_ child we are. */ + if (n->left == NULL) + { r = n->parent; - while (r != NULL) + while ((r != NULL) && (r->parent != NULL)) { - /* stop if a smaller node is found */ - if (t->compare (n, r) > 0) /* n > r */ + if (r->right == n) break; - r = r->parent; + n = r; + r = n->parent; + } + + /* n->left == NULL && r == NULL => t is root and has no next + * r->right != n => r->left = n => r->parent == NULL */ + if ((r == NULL) || (r->right != n)) + { + assert ((r == NULL) || (r->parent == NULL)); + return (NULL); + } + else + { + assert (r->right == n); + return (r); } } else @@ -332,25 +352,25 @@ void *avl_node_prev (avl_tree_t *t, avl_node_t *n) } return (r); -} /* void *avl_node_prev */ +} /* c_avl_node_t *c_avl_node_prev */ -static int _remove (avl_tree_t *t, avl_node_t *n) +static int _remove (c_avl_tree_t *t, c_avl_node_t *n) { assert ((t != NULL) && (n != NULL)); if ((n->left != NULL) && (n->right != NULL)) { - avl_node_t *r; /* replacement node */ + c_avl_node_t *r; /* replacement node */ if (BALANCE (n) > 0) /* left subtree is higher */ { assert (n->left != NULL); - r = avl_node_prev (t, n); + r = c_avl_node_prev (n); } else /* right subtree is higher */ { assert (n->right != NULL); - r = avl_node_next (t, n); + r = c_avl_node_next (n); } assert ((r->left == NULL) || (r->right == NULL)); @@ -447,11 +467,14 @@ static int _remove (avl_tree_t *t, avl_node_t *n) /* * public functions */ -avl_tree_t *avl_create (int (*compare) (const void *, const void *)) +c_avl_tree_t *c_avl_create (int (*compare) (const void *, const void *)) { - avl_tree_t *t; + c_avl_tree_t *t; + + if (compare == NULL) + return (NULL); - if ((t = (avl_tree_t *) malloc (sizeof (avl_tree_t))) == NULL) + if ((t = (c_avl_tree_t *) malloc (sizeof (c_avl_tree_t))) == NULL) return (NULL); t->root = NULL; @@ -460,19 +483,21 @@ avl_tree_t *avl_create (int (*compare) (const void *, const void *)) return (t); } -void avl_destroy (avl_tree_t *t) +void c_avl_destroy (c_avl_tree_t *t) { + if (t == NULL) + return; free_node (t->root); free (t); } -int avl_insert (avl_tree_t *t, void *key, void *value) +int c_avl_insert (c_avl_tree_t *t, void *key, void *value) { - avl_node_t *new; - avl_node_t *nptr; + c_avl_node_t *new; + c_avl_node_t *nptr; int cmp; - if ((new = (avl_node_t *) malloc (sizeof (avl_node_t))) == NULL) + if ((new = (c_avl_node_t *) malloc (sizeof (c_avl_node_t))) == NULL) return (-1); new->key = key; @@ -495,7 +520,7 @@ int avl_insert (avl_tree_t *t, void *key, void *value) if (cmp == 0) { free_node (new); - return (-1); + return (1); } else if (cmp < 0) { @@ -531,11 +556,11 @@ int avl_insert (avl_tree_t *t, void *key, void *value) verify_tree (t->root); return (0); -} /* int avl_insert */ +} /* int c_avl_insert */ -int avl_remove (avl_tree_t *t, void *key, void **rkey, void **rvalue) +int c_avl_remove (c_avl_tree_t *t, const void *key, void **rkey, void **rvalue) { - avl_node_t *n; + c_avl_node_t *n; int status; assert (t != NULL); @@ -552,43 +577,31 @@ int avl_remove (avl_tree_t *t, void *key, void **rkey, void **rvalue) status = _remove (t, n); verify_tree (t->root); return (status); -} /* void *avl_remove */ +} /* void *c_avl_remove */ -int avl_get (avl_tree_t *t, const void *key, void **value) +int c_avl_get (c_avl_tree_t *t, const void *key, void **value) { - avl_node_t *n; + c_avl_node_t *n; - assert (value != NULL); + assert (t != NULL); n = search (t, key); if (n == NULL) return (-1); - *value = n->value; + if (value != NULL) + *value = n->value; return (0); } -avl_iterator_t *avl_get_iterator (avl_tree_t *t) +int c_avl_pick (c_avl_tree_t *t, void **key, void **value) { - avl_node_t *n; - - if (t == NULL) - return (NULL); + c_avl_node_t *n; + c_avl_node_t *p; - for (n = t->root; n != NULL; n = n->left) - if (n->left == NULL) - break; - - return (avl_create_iterator (t, n)); -} /* avl_iterator_t *avl_get_iterator */ - -int avl_pick (avl_tree_t *t, void **key, void **value) -{ - avl_node_t *n; - avl_node_t *p; - - assert ((key != NULL) && (value != NULL)); + if ((key == NULL) || (value == NULL)) + return (-1); if (t->root == NULL) return (-1); @@ -619,43 +632,83 @@ int avl_pick (avl_tree_t *t, void **key, void **value) rebalance (t, p); return (0); -} /* int avl_pick */ +} /* int c_avl_pick */ -void *avl_iterator_next (avl_iterator_t *iter) +c_avl_iterator_t *c_avl_get_iterator (c_avl_tree_t *t) { - avl_node_t *n; + c_avl_iterator_t *iter; - if ((iter == NULL) || (iter->node == NULL)) + if (t == NULL) return (NULL); - n = avl_node_next (iter->tree, iter->node); + iter = (c_avl_iterator_t *) malloc (sizeof (c_avl_iterator_t)); + if (iter == NULL) + return (NULL); + memset (iter, '\0', sizeof (c_avl_iterator_t)); + iter->tree = t; + + return (iter); +} /* c_avl_iterator_t *c_avl_get_iterator */ + +int c_avl_iterator_next (c_avl_iterator_t *iter, void **key, void **value) +{ + c_avl_node_t *n; + + if ((iter == NULL) || (key == NULL) || (value == NULL)) + return (-1); + + if (iter->node == NULL) + { + for (n = iter->tree->root; n != NULL; n = n->left) + if (n->left == NULL) + break; + iter->node = n; + } + else + { + n = c_avl_node_next (iter->node); + } if (n == NULL) - return (NULL); + return (-1); iter->node = n; - return (n); + *key = n->key; + *value = n->value; -} + return (0); +} /* int c_avl_iterator_next */ -void *avl_iterator_prev (avl_iterator_t *iter) +int c_avl_iterator_prev (c_avl_iterator_t *iter, void **key, void **value) { - avl_node_t *n; + c_avl_node_t *n; - if ((iter == NULL) || (iter->node == NULL)) - return (NULL); + if ((iter == NULL) || (key == NULL) || (value == NULL)) + return (-1); - n = avl_node_prev (iter->tree, iter->node); + if (iter->node == NULL) + { + for (n = iter->tree->root; n != NULL; n = n->left) + if (n->right == NULL) + break; + iter->node = n; + } + else + { + n = c_avl_node_prev (iter->node); + } if (n == NULL) - return (NULL); + return (-1); iter->node = n; - return (n); + *key = n->key; + *value = n->value; -} + return (0); +} /* int c_avl_iterator_prev */ -void avl_iterator_destroy (avl_iterator_t *iter) +void c_avl_iterator_destroy (c_avl_iterator_t *iter) { free (iter); }