#include <stdio.h>
#include "util.h"
#include "avl.h"
Go to the source code of this file.
Defines | |
#define | HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height) |
#define | BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left)) |
#define | compute_height(node) |
#define | COMPARE(key, nodekey, compare) |
#define | STACK_SIZE 50 |
Functions | |
static avl_node * | new_node (char *key, char *value) |
static avl_node * | find_rightmost (avl_node **node_p) |
static void | do_rebalance (avl_node ***stack_nodep, int stack_n) |
static int | rotate_left (avl_node **node_p) |
static int | rotate_right (avl_node **node_p) |
static int | do_check_tree (avl_node *node, int(*compar)(const void *, const void *), int *error) |
avl_tree * | avl_init_table (int(*compar)(const void *, const void *)) |
int | avl_lookup (avl_tree *tree, const void *key, void *value_p) |
int | avl_first (avl_tree *tree, char **key_p, char **value_p) |
int | avl_last (avl_tree *tree, char **key_p, char **value_p) |
int | avl_insert (avl_tree *tree, void *key, void *value) |
int | avl_find_or_add (avl_tree *tree, char *key, char ***slot_p) |
int | avl_delete (avl_tree *tree, void *key_p, void *value_p) |
static void | avl_record_gen_forward (avl_node *node, avl_generator *gen) |
static void | avl_record_gen_backward (avl_node *node, avl_generator *gen) |
avl_generator * | avl_init_gen (avl_tree *tree, int dir) |
int | avl_gen (avl_generator *gen, char **key_p, char **value_p) |
void | avl_free_gen (avl_generator *gen) |
static void | avl_walk_forward (avl_node *node, void(*func)(const void *, const void *)) |
static void | avl_walk_backward (avl_node *node, void(*func)(const void *, const void *)) |
void | avl_foreach (avl_tree *tree, void(*func)(const void *, const void *), int direction) |
static void | free_entry (avl_node *node, void(*key_free)(char *), void(*value_free)(char *)) |
void | avl_free_table (avl_tree *tree, void(*key_free)(char *), void(*value_free)(char *)) |
int | avl_count (avl_tree *tree) |
int | avl_numcmp (const void *x, const void *y) |
int | avl_check_tree (avl_tree *tree) |
#define BALANCE | ( | node | ) | (HEIGHT((node)->right) - HEIGHT((node)->left)) |
#define COMPARE | ( | key, | |||
nodekey, | |||||
compare | ) |
((compare == avl_numcmp) ? \ (long) key - (long) nodekey : \ (*compare)(key, nodekey))
#define compute_height | ( | node | ) |
#define HEIGHT | ( | node | ) | (node == NIL(avl_node) ? -1 : (node)->height) |
int avl_check_tree | ( | avl_tree * | tree | ) |
int avl_count | ( | avl_tree * | tree | ) |
Definition at line 454 of file avl.c.
00455 { 00456 return tree->num_entries; 00457 }
int avl_delete | ( | avl_tree * | tree, | |
void * | key_p, | |||
void * | value_p | |||
) |
Definition at line 185 of file avl.c.
00186 { 00187 avl_node **node_p, *node, *rightmost; 00188 int stack_n = 0; 00189 char *key = *(char **) key_p; 00190 int (*compare)(const void *, const void *) = tree->compar, diff; 00191 avl_node **stack_nodep[STACK_SIZE]; 00192 00193 node_p = &tree->root; 00194 00195 /* Walk down the tree saving the path; return if not found */ 00196 while ((node = *node_p) != NIL(avl_node)) { 00197 diff = COMPARE(key, node->key, compare); 00198 if (diff == 0) goto delete_item; 00199 stack_nodep[stack_n++] = node_p; 00200 node_p = (diff < 0) ? &node->left : &node->right; 00201 } 00202 return 0; /* not found */ 00203 00204 /* prepare to delete node and replace it with rightmost of left tree */ 00205 delete_item: 00206 *(char **) key_p = node->key; 00207 if (value_p != NULL) *(char **)value_p = node->value; 00208 if (node->left == NIL(avl_node)) { 00209 *node_p = node->right; 00210 } else { 00211 rightmost = find_rightmost(&node->left); 00212 rightmost->left = node->left; 00213 rightmost->right = node->right; 00214 rightmost->height = -2; /* mark bogus height for do_rebal */ 00215 *node_p = rightmost; 00216 stack_nodep[stack_n++] = node_p; 00217 } 00218 FREE(node); 00219 00220 /* work our way back up, re-balancing the tree */ 00221 do_rebalance(stack_nodep, stack_n); 00222 tree->num_entries--; 00223 tree->modified = 1; 00224 return 1; 00225 }
int avl_find_or_add | ( | avl_tree * | tree, | |
char * | key, | |||
char *** | slot_p | |||
) |
Definition at line 154 of file avl.c.
00155 { 00156 register avl_node **node_p, *node; 00157 register int stack_n = 0; 00158 register int (*compare)(const void *, const void *) = tree->compar; 00159 avl_node **stack_nodep[STACK_SIZE]; 00160 int diff; 00161 00162 node_p = &tree->root; 00163 00164 /* walk down the tree (saving the path); stop at insertion point */ 00165 while ((node = *node_p) != NIL(avl_node)) { 00166 stack_nodep[stack_n++] = node_p; 00167 diff = COMPARE(key, node->key, compare); 00168 if (diff == 0) { 00169 if (slot_p != 0) *slot_p = &node->value; 00170 return 1; /* found */ 00171 } 00172 node_p = (diff < 0) ? &node->left : &node->right; 00173 } 00174 00175 /* insert the item and re-balance the tree */ 00176 *node_p = new_node(key, NIL(char)); 00177 if (slot_p != 0) *slot_p = &(*node_p)->value; 00178 do_rebalance(stack_nodep, stack_n); 00179 tree->num_entries++; 00180 tree->modified = 1; 00181 return 0; /* not already in tree */ 00182 }
int avl_first | ( | avl_tree * | tree, | |
char ** | key_p, | |||
char ** | value_p | |||
) |
Definition at line 91 of file avl.c.
00092 { 00093 register avl_node *node; 00094 00095 if (tree->root == 0) { 00096 return 0; /* no entries */ 00097 } else { 00098 /* walk down the tree; stop at leftmost leaf */ 00099 for(node = tree->root; node->left != 0; node = node->left) { 00100 } 00101 if (key_p != NIL(char *)) *key_p = node->key; 00102 if (value_p != NIL(char *)) *value_p = node->value; 00103 return 1; 00104 } 00105 }
void avl_foreach | ( | avl_tree * | tree, | |
void(*)(const void *, const void *) | func, | |||
int | direction | |||
) |
Definition at line 413 of file avl.c.
00417 { 00418 if (direction == AVL_FORWARD) { 00419 avl_walk_forward(tree->root, func); 00420 } else { 00421 avl_walk_backward(tree->root, func); 00422 } 00423 }
void avl_free_gen | ( | avl_generator * | gen | ) |
void avl_free_table | ( | avl_tree * | tree, | |
void(*)(char *) | key_free, | |||
void(*)(char *) | value_free | |||
) |
Definition at line 443 of file avl.c.
00447 { 00448 free_entry(tree->root, key_free, value_free); 00449 FREE(tree); 00450 }
int avl_gen | ( | avl_generator * | gen, | |
char ** | key_p, | |||
char ** | value_p | |||
) |
Definition at line 273 of file avl.c.
00274 { 00275 avl_node *node; 00276 00277 if (gen->count == gen->tree->num_entries) { 00278 return 0; 00279 } else { 00280 node = gen->nodelist[gen->count++]; 00281 if (key_p != NIL(char *)) *key_p = node->key; 00282 if (value_p != NIL(char *)) *value_p = node->value; 00283 return 1; 00284 } 00285 }
avl_generator* avl_init_gen | ( | avl_tree * | tree, | |
int | dir | |||
) |
Definition at line 250 of file avl.c.
00251 { 00252 avl_generator *gen; 00253 00254 /* what a hack */ 00255 gen = ALLOC(avl_generator, 1); 00256 gen->tree = tree; 00257 gen->nodelist = ALLOC(avl_node *, avl_count(tree)); 00258 gen->count = 0; 00259 if (dir == AVL_FORWARD) { 00260 avl_record_gen_forward(tree->root, gen); 00261 } else { 00262 avl_record_gen_backward(tree->root, gen); 00263 } 00264 gen->count = 0; 00265 00266 /* catch any attempt to modify the tree while we generate */ 00267 tree->modified = 0; 00268 return gen; 00269 }
avl_tree* avl_init_table | ( | int(*)(const void *, const void *) | compar | ) |
int avl_insert | ( | avl_tree * | tree, | |
void * | key, | |||
void * | value | |||
) |
Definition at line 125 of file avl.c.
00126 { 00127 avl_node **node_p, *node; 00128 int stack_n = 0; 00129 int (*compare)(const void *, const void *) = tree->compar; 00130 avl_node **stack_nodep[STACK_SIZE]; 00131 int diff, status; 00132 00133 node_p = &tree->root; 00134 00135 /* walk down the tree (saving the path); stop at insertion point */ 00136 status = 0; 00137 while ((node = *node_p) != NIL(avl_node)) { 00138 stack_nodep[stack_n++] = node_p; 00139 diff = COMPARE(key, node->key, compare); 00140 if (diff == 0) status = 1; 00141 node_p = (diff < 0) ? &node->left : &node->right; 00142 } 00143 00144 /* insert the item and re-balance the tree */ 00145 *node_p = new_node((char *)key, (char *)value); 00146 do_rebalance(stack_nodep, stack_n); 00147 tree->num_entries++; 00148 tree->modified = 1; 00149 return status; 00150 }
int avl_last | ( | avl_tree * | tree, | |
char ** | key_p, | |||
char ** | value_p | |||
) |
Definition at line 108 of file avl.c.
00109 { 00110 register avl_node *node; 00111 00112 if (tree->root == 0) { 00113 return 0; /* no entries */ 00114 } else { 00115 /* walk down the tree; stop at rightmost leaf */ 00116 for(node = tree->root; node->right != 0; node = node->right) { 00117 } 00118 if (key_p != NIL(char *)) *key_p = node->key; 00119 if (value_p != NIL(char *)) *value_p = node->value; 00120 return 1; 00121 } 00122 }
int avl_lookup | ( | avl_tree * | tree, | |
const void * | key, | |||
void * | value_p | |||
) |
Definition at line 72 of file avl.c.
00073 { 00074 avl_node *node; 00075 int (*compare)(const void *, const void *) = tree->compar, diff; 00076 00077 node = tree->root; 00078 while (node != NIL(avl_node)) { 00079 diff = COMPARE(key, node->key, compare); 00080 if (diff == 0) { 00081 /* got a match */ 00082 if (value_p != NULL) *(char **)value_p = node->value; 00083 return 1; 00084 } 00085 node = (diff < 0) ? node->left : node->right; 00086 } 00087 return 0; 00088 }
int avl_numcmp | ( | const void * | x, | |
const void * | y | |||
) |
static void avl_record_gen_backward | ( | avl_node * | node, | |
avl_generator * | gen | |||
) | [static] |
Definition at line 239 of file avl.c.
00240 { 00241 if (node != NIL(avl_node)) { 00242 avl_record_gen_backward(node->right, gen); 00243 gen->nodelist[gen->count++] = node; 00244 avl_record_gen_backward(node->left, gen); 00245 } 00246 }
static void avl_record_gen_forward | ( | avl_node * | node, | |
avl_generator * | gen | |||
) | [static] |
Definition at line 228 of file avl.c.
00229 { 00230 if (node != NIL(avl_node)) { 00231 avl_record_gen_forward(node->left, gen); 00232 gen->nodelist[gen->count++] = node; 00233 avl_record_gen_forward(node->right, gen); 00234 } 00235 }
static void avl_walk_backward | ( | avl_node * | node, | |
void(*)(const void *, const void *) | func | |||
) | [static] |
Definition at line 402 of file avl.c.
00403 { 00404 if (node != NIL(avl_node)) { 00405 avl_walk_backward(node->right, func); 00406 (*func)(node->key, node->value); 00407 avl_walk_backward(node->left, func); 00408 } 00409 }
static void avl_walk_forward | ( | avl_node * | node, | |
void(*)(const void *, const void *) | func | |||
) | [static] |
Definition at line 391 of file avl.c.
00392 { 00393 if (node != NIL(avl_node)) { 00394 avl_walk_forward(node->left, func); 00395 (*func)(node->key, node->value); 00396 avl_walk_forward(node->right, func); 00397 } 00398 }
static int do_check_tree | ( | avl_node * | node, | |
int(*)(const void *, const void *) | compar, | |||
int * | error | |||
) | [static] |
Definition at line 490 of file avl.c.
00494 { 00495 int l_height, r_height, comp_height, bal; 00496 00497 if (node == NIL(avl_node)) { 00498 return -1; 00499 } 00500 00501 r_height = do_check_tree(node->right, compar, error); 00502 l_height = do_check_tree(node->left, compar, error); 00503 00504 comp_height = MAX(l_height, r_height) + 1; 00505 bal = r_height - l_height; 00506 00507 if (comp_height != node->height) { 00508 (void) printf("Bad height for 0x%p: computed=%d stored=%d\n", 00509 (void *) node, comp_height, node->height); 00510 ++*error; 00511 } 00512 00513 if (bal > 1 || bal < -1) { 00514 (void) printf("Out of balance at node 0x%p, balance = %d\n", 00515 (void *) node, bal); 00516 ++*error; 00517 } 00518 00519 if (node->left != NIL(avl_node) && 00520 (*compar)(node->left->key, node->key) > 0) { 00521 (void) printf("Bad ordering between 0x%p and 0x%p", 00522 (void *) node, (void *) node->left); 00523 ++*error; 00524 } 00525 00526 if (node->right != NIL(avl_node) && 00527 (*compar)(node->key, node->right->key) > 0) { 00528 (void) printf("Bad ordering between 0x%p and 0x%p", 00529 (void *) node, (void *) node->right); 00530 ++*error; 00531 } 00532 00533 return comp_height; 00534 }
static void do_rebalance | ( | avl_node *** | stack_nodep, | |
int | stack_n | |||
) | [static] |
Definition at line 317 of file avl.c.
00318 { 00319 register avl_node **node_p, *node; 00320 register int hl, hr; 00321 int height; 00322 00323 /* work our way back up, re-balancing the tree */ 00324 while (--stack_n >= 0) { 00325 node_p = stack_nodep[stack_n]; 00326 node = *node_p; 00327 hl = HEIGHT(node->left); /* watch for NIL */ 00328 hr = HEIGHT(node->right); /* watch for NIL */ 00329 if ((hr - hl) < -1) { 00330 rotate_right(node_p); 00331 } else if ((hr - hl) > 1) { 00332 rotate_left(node_p); 00333 } else { 00334 height = MAX(hl, hr) + 1; 00335 if (height == node->height) break; 00336 node->height = height; 00337 } 00338 } 00339 }
Definition at line 297 of file avl.c.
00298 { 00299 register avl_node *node; 00300 register int stack_n = 0; 00301 avl_node **stack_nodep[STACK_SIZE]; 00302 00303 node = *node_p; 00304 while (node->right != NIL(avl_node)) { 00305 stack_nodep[stack_n++] = node_p; 00306 node_p = &node->right; 00307 node = *node_p; 00308 } 00309 *node_p = node->left; 00310 00311 do_rebalance(stack_nodep, stack_n); 00312 return node; 00313 }
static void free_entry | ( | avl_node * | node, | |
void(*)(char *) | key_free, | |||
void(*)(char *) | value_free | |||
) | [static] |
Definition at line 427 of file avl.c.
00431 { 00432 if (node != NIL(avl_node)) { 00433 free_entry(node->left, key_free, value_free); 00434 free_entry(node->right, key_free, value_free); 00435 if (key_free != 0) (*key_free)(node->key); 00436 if (value_free != 0) (*value_free)(node->value); 00437 FREE(node); 00438 } 00439 }
static avl_node * new_node | ( | char * | key, | |
char * | value | |||
) | [static] |
static int rotate_left | ( | avl_node ** | node_p | ) | [static] |
Definition at line 342 of file avl.c.
00343 { 00344 register avl_node *old_root = *node_p, *new_root, *new_right; 00345 00346 if (BALANCE(old_root->right) >= 0) { 00347 *node_p = new_root = old_root->right; 00348 old_root->right = new_root->left; 00349 new_root->left = old_root; 00350 } else { 00351 new_right = old_root->right; 00352 *node_p = new_root = new_right->left; 00353 old_root->right = new_root->left; 00354 new_right->left = new_root->right; 00355 new_root->right = new_right; 00356 new_root->left = old_root; 00357 compute_height(new_right); 00358 } 00359 compute_height(old_root); 00360 compute_height(new_root); 00361 00362 return 0; 00363 }
static int rotate_right | ( | avl_node ** | node_p | ) | [static] |
Definition at line 367 of file avl.c.
00368 { 00369 register avl_node *old_root = *node_p, *new_root, *new_left; 00370 00371 if (BALANCE(old_root->left) <= 0) { 00372 *node_p = new_root = old_root->left; 00373 old_root->left = new_root->right; 00374 new_root->right = old_root; 00375 } else { 00376 new_left = old_root->left; 00377 *node_p = new_root = new_left->right; 00378 old_root->left = new_root->right; 00379 new_left->right = new_root->left; 00380 new_root->left = new_left; 00381 new_root->right = old_root; 00382 compute_height(new_left); 00383 } 00384 compute_height(old_root); 00385 compute_height(new_root); 00386 00387 return 0; 00388 }