00001
00002
00003
00004
00005
00006
00007
00008 #include <stdio.h>
00009
00010 #ifndef PACKAGE
00011 #include "util.h"
00012 #endif
00013
00014 #include "avl.h"
00015
00016 #ifdef PACKAGE
00017 extern char *malloc();
00018 #ifdef ultrix
00019 extern void free();
00020 #endif
00021
00022 #define MAX(a,b) ((a) > (b) ? (a) : (b))
00023
00024 #define NIL(type) \
00025 ((type *) 0)
00026 #define ALLOC(type, num) \
00027 ((type *) malloc(sizeof(type) * (num)))
00028 #define REALLOC(type, obj, num) \
00029 ((type *) realloc((char *) obj, sizeof(type) * (num)))
00030 #define FREE(obj) \
00031 free((char *) (obj))
00032 #endif
00033
00034
00035 #define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height)
00036 #define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left))
00037
00038 #define compute_height(node) { \
00039 int x=HEIGHT(node->left), y=HEIGHT(node->right); \
00040 (node)->height = MAX(x,y) + 1; \
00041 }
00042
00043 #define COMPARE(key, nodekey, compare) \
00044 ((compare == avl_numcmp) ? \
00045 (long) key - (long) nodekey : \
00046 (*compare)(key, nodekey))
00047
00048
00049 #define STACK_SIZE 50
00050
00051 static avl_node *new_node(char *key, char *value);
00052 static avl_node *find_rightmost(avl_node **node_p);
00053 static void do_rebalance(avl_node ***stack_nodep, int stack_n);
00054 static int rotate_left(avl_node **node_p);
00055 static int rotate_right(avl_node **node_p);
00056 static int do_check_tree(avl_node *node, int (*compar)(const void *, const void *), int *error);
00057
00058 avl_tree *
00059 avl_init_table(int (*compar)(const void *, const void *))
00060 {
00061 avl_tree *tree;
00062
00063 tree = ALLOC(avl_tree, 1);
00064 tree->root = NIL(avl_node);
00065 tree->compar = compar;
00066 tree->num_entries = 0;
00067 return tree;
00068 }
00069
00070
00071 int
00072 avl_lookup(avl_tree *tree, const void *key, void *value_p)
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
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 }
00089
00090 int
00091 avl_first(avl_tree *tree, char **key_p, char **value_p)
00092 {
00093 register avl_node *node;
00094
00095 if (tree->root == 0) {
00096 return 0;
00097 } else {
00098
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 }
00106
00107 int
00108 avl_last(avl_tree *tree, char **key_p, char **value_p)
00109 {
00110 register avl_node *node;
00111
00112 if (tree->root == 0) {
00113 return 0;
00114 } else {
00115
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 }
00123
00124 int
00125 avl_insert(avl_tree *tree, void *key, void *value)
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
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
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 }
00151
00152
00153 int
00154 avl_find_or_add(avl_tree *tree, char *key, char ***slot_p)
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
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;
00171 }
00172 node_p = (diff < 0) ? &node->left : &node->right;
00173 }
00174
00175
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;
00182 }
00183
00184 int
00185 avl_delete(avl_tree *tree, void *key_p, void *value_p)
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
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;
00203
00204
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;
00215 *node_p = rightmost;
00216 stack_nodep[stack_n++] = node_p;
00217 }
00218 FREE(node);
00219
00220
00221 do_rebalance(stack_nodep, stack_n);
00222 tree->num_entries--;
00223 tree->modified = 1;
00224 return 1;
00225 }
00226
00227 static void
00228 avl_record_gen_forward(avl_node *node, avl_generator *gen)
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 }
00236
00237
00238 static void
00239 avl_record_gen_backward(avl_node *node, avl_generator *gen)
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 }
00247
00248
00249 avl_generator *
00250 avl_init_gen(avl_tree *tree, int dir)
00251 {
00252 avl_generator *gen;
00253
00254
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
00267 tree->modified = 0;
00268 return gen;
00269 }
00270
00271
00272 int
00273 avl_gen(avl_generator *gen, char **key_p, char **value_p)
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 }
00286
00287
00288 void
00289 avl_free_gen(avl_generator *gen)
00290 {
00291 FREE(gen->nodelist);
00292 FREE(gen);
00293 }
00294
00295
00296 static avl_node *
00297 find_rightmost(avl_node **node_p)
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 }
00314
00315
00316 static void
00317 do_rebalance(avl_node ***stack_nodep, int stack_n)
00318 {
00319 register avl_node **node_p, *node;
00320 register int hl, hr;
00321 int height;
00322
00323
00324 while (--stack_n >= 0) {
00325 node_p = stack_nodep[stack_n];
00326 node = *node_p;
00327 hl = HEIGHT(node->left);
00328 hr = HEIGHT(node->right);
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 }
00340
00341 static int
00342 rotate_left(avl_node **node_p)
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 }
00364
00365
00366 static int
00367 rotate_right(avl_node **node_p)
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 }
00389
00390 static void
00391 avl_walk_forward(avl_node *node, void (*func)(const void *, const void *))
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 }
00399
00400
00401 static void
00402 avl_walk_backward(avl_node *node, void (*func)(const void *, const void *))
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 }
00410
00411
00412 void
00413 avl_foreach(
00414 avl_tree *tree,
00415 void (*func)(const void *, const void *),
00416 int direction)
00417 {
00418 if (direction == AVL_FORWARD) {
00419 avl_walk_forward(tree->root, func);
00420 } else {
00421 avl_walk_backward(tree->root, func);
00422 }
00423 }
00424
00425
00426 static void
00427 free_entry(
00428 avl_node *node,
00429 void (*key_free)(char *),
00430 void (*value_free)(char *))
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 }
00440
00441
00442 void
00443 avl_free_table(
00444 avl_tree *tree,
00445 void (*key_free)(char *),
00446 void (*value_free)(char *))
00447 {
00448 free_entry(tree->root, key_free, value_free);
00449 FREE(tree);
00450 }
00451
00452
00453 int
00454 avl_count(avl_tree *tree)
00455 {
00456 return tree->num_entries;
00457 }
00458
00459
00460 static avl_node *
00461 new_node(char *key, char *value)
00462 {
00463 register avl_node *newn;
00464
00465 newn = ALLOC(avl_node, 1);
00466 newn->key = key;
00467 newn->value = value;
00468 newn->height = 0;
00469 newn->left = newn->right = NIL(avl_node);
00470 return newn;
00471 }
00472
00473
00474 int
00475 avl_numcmp(const void *x, const void *y)
00476 {
00477 return (long) x - (long) y;
00478 }
00479
00480 int
00481 avl_check_tree(avl_tree *tree)
00482 {
00483 int error = 0;
00484 (void) do_check_tree(tree->root, tree->compar, &error);
00485 return error;
00486 }
00487
00488
00489 static int
00490 do_check_tree(
00491 avl_node *node,
00492 int (*compar)(const void *, const void *),
00493 int *error)
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 }