abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
avl.c
Go to the documentation of this file.
1 /*
2  * Revision Control Information
3  *
4  * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.c,v $
5  * $Author: sis $
6  * $Revision: 1.3 $
7  * $Date: 1994/07/15 23:00:40 $
8  *
9  */
10 /* LINTLIBRARY */
11 
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 #include "avl.h"
17 
19 
20 
21 
22 
23 #define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height)
24 #define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left))
25 
26 #define compute_height(node) { \
27  int x=HEIGHT(node->left), y=HEIGHT(node->right); \
28  (node)->height = MAX(x,y) + 1; \
29 }
30 
31 #define COMPARE(key, nodekey, compare) \
32  ((compare == avl_numcmp) ? \
33  (int) key - (int) nodekey : \
34  (*compare)(key, nodekey))
35 
36 
37 #define STACK_SIZE 50
38 
39 static avl_node *new_node ();
40 static avl_node *find_rightmost ();
41 static void do_rebalance ();
42 static rotate_left ();
43 static rotate_right ();
44 static int do_check_tree ();
45 
46 avl_tree *
48  int (*compar) ();
49 {
50  avl_tree *tree;
51 
52  tree = ALLOC (avl_tree, 1);
53  tree->root = NIL (avl_node);
54  tree->compar = compar;
55  tree->num_entries = 0;
56  return tree;
57 }
58 
59 
60 
61 avl_lookup (tree, key, value_p)
62  avl_tree *tree;
63  register char *key;
64  char **value_p;
65 {
66  register avl_node *node;
67  register int (*compare) () = tree->compar, diff;
68 
69  node = tree->root;
70  while (node != NIL (avl_node))
71  {
72  diff = COMPARE (key, node->key, compare);
73  if (diff == 0)
74  {
75  /* got a match */
76  if (value_p != NIL (char *))
77  *value_p = node->value;
78  return 1;
79  }
80  node = (diff < 0) ? node->left : node->right;
81  }
82  return 0;
83 }
84 
85 avl_first (tree, key_p, value_p)
86  avl_tree *tree;
87  char **key_p;
88  char **value_p;
89 {
90  register avl_node *node;
91 
92  if (tree->root == 0)
93  {
94  return 0; /* no entries */
95  }
96  else
97  {
98  /* walk down the tree; stop at leftmost leaf */
99  for (node = tree->root; node->left != 0; node = node->left)
100  {
101  }
102  if (key_p != NIL (char *))
103  *key_p = node->key;
104  if (value_p != NIL (char *))
105  *value_p = node->value;
106  return 1;
107  }
108 }
109 
110 
111 avl_last (tree, key_p, value_p)
112  avl_tree *tree;
113  char **key_p;
114  char **value_p;
115 {
116  register avl_node *node;
117 
118  if (tree->root == 0)
119  {
120  return 0; /* no entries */
121  }
122  else
123  {
124  /* walk down the tree; stop at rightmost leaf */
125  for (node = tree->root; node->right != 0; node = node->right)
126  {
127  }
128  if (key_p != NIL (char *))
129  *key_p = node->key;
130  if (value_p != NIL (char *))
131  *value_p = node->value;
132  return 1;
133  }
134 }
135 
137  avl_tree *tree;
138  char *key;
139  char *value;
140 {
141  register avl_node **node_p, *node;
142  register int stack_n = 0;
143  register int (*compare) () = tree->compar;
144  avl_node **stack_nodep[STACK_SIZE];
145  int diff, status;
146 
147  node_p = &tree->root;
148 
149  /* walk down the tree (saving the path); stop at insertion point */
150  status = 0;
151  while ((node = *node_p) != NIL (avl_node))
152  {
153  stack_nodep[stack_n++] = node_p;
154  diff = COMPARE (key, node->key, compare);
155  if (diff == 0)
156  status = 1;
157  node_p = (diff < 0) ? &node->left : &node->right;
158  }
159 
160  /* insert the item and re-balance the tree */
161  *node_p = new_node (key, value);
162  do_rebalance (stack_nodep, stack_n);
163  tree->num_entries++;
164  tree->modified = 1;
165  return status;
166 }
167 
168 
169 
170 avl_find_or_add (tree, key, slot_p)
171  avl_tree *tree;
172  char *key;
173  char ***slot_p;
174 {
175  register avl_node **node_p, *node;
176  register int stack_n = 0;
177  register int (*compare) () = tree->compar;
178  avl_node **stack_nodep[STACK_SIZE];
179  int diff;
180 
181  node_p = &tree->root;
182 
183  /* walk down the tree (saving the path); stop at insertion point */
184  while ((node = *node_p) != NIL (avl_node))
185  {
186  stack_nodep[stack_n++] = node_p;
187  diff = COMPARE (key, node->key, compare);
188  if (diff == 0)
189  {
190  if (slot_p != 0)
191  *slot_p = &node->value;
192  return 1; /* found */
193  }
194  node_p = (diff < 0) ? &node->left : &node->right;
195  }
196 
197  /* insert the item and re-balance the tree */
198  *node_p = new_node (key, NIL (char));
199  if (slot_p != 0)
200  *slot_p = &(*node_p)->value;
201  do_rebalance (stack_nodep, stack_n);
202  tree->num_entries++;
203  tree->modified = 1;
204  return 0; /* not already in tree */
205 }
206 
207 avl_delete (tree, key_p, value_p)
208  avl_tree *tree;
209  char **key_p;
210  char **value_p;
211 {
212  register avl_node **node_p, *node, *rightmost;
213  register int stack_n = 0;
214  char *key = *key_p;
215  int (*compare) () = tree->compar, diff;
216  avl_node **stack_nodep[STACK_SIZE];
217 
218  node_p = &tree->root;
219 
220  /* Walk down the tree saving the path; return if not found */
221  while ((node = *node_p) != NIL (avl_node))
222  {
223  diff = COMPARE (key, node->key, compare);
224  if (diff == 0)
225  goto delete_item;
226  stack_nodep[stack_n++] = node_p;
227  node_p = (diff < 0) ? &node->left : &node->right;
228  }
229  return 0; /* not found */
230 
231  /* prepare to delete node and replace it with rightmost of left tree */
232  delete_item:
233  *key_p = node->key;
234  if (value_p != 0)
235  *value_p = node->value;
236  if (node->left == NIL (avl_node))
237  {
238  *node_p = node->right;
239  }
240  else
241  {
242  rightmost = find_rightmost (&node->left);
243  rightmost->left = node->left;
244  rightmost->right = node->right;
245  rightmost->height = -2; /* mark bogus height for do_rebal */
246  *node_p = rightmost;
247  stack_nodep[stack_n++] = node_p;
248  }
249  FREE (node);
250 
251  /* work our way back up, re-balancing the tree */
252  do_rebalance (stack_nodep, stack_n);
253  tree->num_entries--;
254  tree->modified = 1;
255  return 1;
256 }
257 
258 static void
260  avl_node *node;
261  avl_generator *gen;
262 {
263  if (node != NIL (avl_node))
264  {
265  avl_record_gen_forward (node->left, gen);
266  gen->nodelist[gen->count++] = node;
267  avl_record_gen_forward (node->right, gen);
268  }
269 }
270 
271 
272 static void
274  avl_node *node;
275  avl_generator *gen;
276 {
277  if (node != NIL (avl_node))
278  {
279  avl_record_gen_backward (node->right, gen);
280  gen->nodelist[gen->count++] = node;
281  avl_record_gen_backward (node->left, gen);
282  }
283 }
284 
285 
287 avl_init_gen (tree, dir)
288  avl_tree *tree;
289  int dir;
290 {
291  avl_generator *gen;
292 
293  /* what a hack */
294  gen = ALLOC (avl_generator, 1);
295  gen->tree = tree;
296  gen->nodelist = ALLOC (avl_node *, avl_count (tree));
297  gen->count = 0;
298  if (dir == AVL_FORWARD)
299  {
300  avl_record_gen_forward (tree->root, gen);
301  }
302  else
303  {
304  avl_record_gen_backward (tree->root, gen);
305  }
306  gen->count = 0;
307 
308  /* catch any attempt to modify the tree while we generate */
309  tree->modified = 0;
310  return gen;
311 }
312 
313 
314 avl_gen (gen, key_p, value_p)
315  avl_generator *gen;
316  char **key_p;
317  char **value_p;
318 {
319  avl_node *node;
320 
321  if (gen->count == gen->tree->num_entries)
322  {
323  return 0;
324  }
325  else
326  {
327  node = gen->nodelist[gen->count++];
328  if (key_p != NIL (char *))
329  *key_p = node->key;
330  if (value_p != NIL (char *))
331  *value_p = node->value;
332  return 1;
333  }
334 }
335 
336 
337 void
339  avl_generator *gen;
340 {
341  FREE (gen->nodelist);
342  FREE (gen);
343 }
344 
345 static avl_node *
347  register avl_node **node_p;
348 {
349  register avl_node *node;
350  register int stack_n = 0;
351  avl_node **stack_nodep[STACK_SIZE];
352 
353  node = *node_p;
354  while (node->right != NIL (avl_node))
355  {
356  stack_nodep[stack_n++] = node_p;
357  node_p = &node->right;
358  node = *node_p;
359  }
360  *node_p = node->left;
361 
362  do_rebalance (stack_nodep, stack_n);
363  return node;
364 }
365 
366 
367 static void
368 do_rebalance (stack_nodep, stack_n)
369  register avl_node ***stack_nodep;
370  register int stack_n;
371 {
372  register avl_node **node_p, *node;
373  register int hl, hr;
374  int height;
375 
376  /* work our way back up, re-balancing the tree */
377  while (--stack_n >= 0)
378  {
379  node_p = stack_nodep[stack_n];
380  node = *node_p;
381  hl = HEIGHT (node->left); /* watch for NIL */
382  hr = HEIGHT (node->right); /* watch for NIL */
383  if ((hr - hl) < -1)
384  {
385  rotate_right (node_p);
386  }
387  else if ((hr - hl) > 1)
388  {
389  rotate_left (node_p);
390  }
391  else
392  {
393  height = MAX (hl, hr) + 1;
394  if (height == node->height)
395  break;
396  node->height = height;
397  }
398  }
399 }
400 
401 static
402 rotate_left (node_p)
403  register avl_node **node_p;
404 {
405  register avl_node *old_root = *node_p, *new_root, *new_right;
406 
407  if (BALANCE (old_root->right) >= 0)
408  {
409  *node_p = new_root = old_root->right;
410  old_root->right = new_root->left;
411  new_root->left = old_root;
412  }
413  else
414  {
415  new_right = old_root->right;
416  *node_p = new_root = new_right->left;
417  old_root->right = new_root->left;
418  new_right->left = new_root->right;
419  new_root->right = new_right;
420  new_root->left = old_root;
421  compute_height (new_right);
422  }
423  compute_height (old_root);
424  compute_height (new_root);
425 }
426 
427 
428 static
429 rotate_right (node_p)
430  avl_node **node_p;
431 {
432  register avl_node *old_root = *node_p, *new_root, *new_left;
433 
434  if (BALANCE (old_root->left) <= 0)
435  {
436  *node_p = new_root = old_root->left;
437  old_root->left = new_root->right;
438  new_root->right = old_root;
439  }
440  else
441  {
442  new_left = old_root->left;
443  *node_p = new_root = new_left->right;
444  old_root->left = new_root->right;
445  new_left->right = new_root->left;
446  new_root->left = new_left;
447  new_root->right = old_root;
448  compute_height (new_left);
449  }
450  compute_height (old_root);
451  compute_height (new_root);
452 }
453 
454 static void
455 avl_walk_forward (node, func)
456  avl_node *node;
457  void (*func) ();
458 {
459  if (node != NIL (avl_node))
460  {
461  avl_walk_forward (node->left, func);
462  (*func) (node->key, node->value);
463  avl_walk_forward (node->right, func);
464  }
465 }
466 
467 
468 static void
469 avl_walk_backward (node, func)
470  avl_node *node;
471  void (*func) ();
472 {
473  if (node != NIL (avl_node))
474  {
475  avl_walk_backward (node->right, func);
476  (*func) (node->key, node->value);
477  avl_walk_backward (node->left, func);
478  }
479 }
480 
481 
482 void
483 avl_foreach (tree, func, direction)
484  avl_tree *tree;
485  void (*func) ();
486  int direction;
487 {
488  if (direction == AVL_FORWARD)
489  {
490  avl_walk_forward (tree->root, func);
491  }
492  else
493  {
494  avl_walk_backward (tree->root, func);
495  }
496 }
497 
498 
499 static void
500 free_entry (node, key_free, value_free)
501  avl_node *node;
502  void (*key_free) ();
503  void (*value_free) ();
504 {
505  if (node != NIL (avl_node))
506  {
507  free_entry (node->left, key_free, value_free);
508  free_entry (node->right, key_free, value_free);
509  if (key_free != 0)
510  (*key_free) (node->key);
511  if (value_free != 0)
512  (*value_free) (node->value);
513  FREE (node);
514  }
515 }
516 
517 
518 void
519 avl_free_table (tree, key_free, value_free)
520  avl_tree *tree;
521  void (*key_free) ();
522  void (*value_free) ();
523 {
524  free_entry (tree->root, key_free, value_free);
525  FREE (tree);
526 }
527 
528 
529 int
530 avl_count (tree)
531  avl_tree *tree;
532 {
533  return tree->num_entries;
534 }
535 
536 static avl_node *
538  char *key;
539  char *value;
540 {
541  register avl_node *new;
542 
543  new = ALLOC (avl_node, 1);
544  new->key = key;
545  new->value = value;
546  new->height = 0;
547  new->left = new->right = NIL (avl_node);
548  return new;
549 }
550 
551 
552 int
554  char *x, *y;
555 {
556  return (int) x - (int) y;
557 }
558 
559 int
561  avl_tree *tree;
562 {
563  int error = 0;
564  (void) do_check_tree (tree->root, tree->compar, &error);
565  return error;
566 }
567 
568 
569 static int
570 do_check_tree (node, compar, error)
571  avl_node *node;
572  int (*compar) ();
573  int *error;
574 {
575  int l_height, r_height, comp_height, bal;
576 
577  if (node == NIL (avl_node))
578  {
579  return -1;
580  }
581 
582  r_height = do_check_tree (node->right, compar, error);
583  l_height = do_check_tree (node->left, compar, error);
584 
585  comp_height = MAX (l_height, r_height) + 1;
586  bal = r_height - l_height;
587 
588  if (comp_height != node->height)
589  {
590  (void) printf ("Bad height for 0x%08x: computed=%d stored=%d\n",
591  node, comp_height, node->height);
592  ++*error;
593  }
594 
595  if (bal > 1 || bal < -1)
596  {
597  (void) printf ("Out of balance at node 0x%08x, balance = %d\n",
598  node, bal);
599  ++*error;
600  }
601 
602  if (node->left != NIL (avl_node) &&
603  (*compar) (node->left->key, node->key) > 0)
604  {
605  (void) printf ("Bad ordering between 0x%08x and 0x%08x",
606  node, node->left);
607  ++*error;
608  }
609 
610  if (node->right != NIL (avl_node) &&
611  (*compar) (node->key, node->right->key) > 0)
612  {
613  (void) printf ("Bad ordering between 0x%08x and 0x%08x",
614  node, node->right);
615  ++*error;
616  }
617 
618  return comp_height;
619 }
621 
int num_entries
Definition: avl.h:49
int height
Definition: avl.h:41
void avl_free_table(avl_tree *tree, void(*)() key_free, void(*)() value_free)
Definition: avl.c:519
avl_find_or_add(avl_tree *tree, char *key, char ***slot_p)
Definition: avl.c:170
static void avl_walk_forward(avl_node *node, void(*)() func)
Definition: avl.c:455
void avl_free_gen(avl_generator *gen)
Definition: avl.c:338
avl_delete(avl_tree *tree, char **key_p, char **value_p)
Definition: avl.c:207
avl_insert(avl_tree *tree, char *key, char *value)
Definition: avl.c:136
char * key
Definition: avl.h:39
static void avl_record_gen_backward(avl_node *node, avl_generator *gen)
Definition: avl.c:273
static avl_node * new_node()
int avl_count(avl_tree *tree)
Definition: avl.c:530
void avl_foreach(avl_tree *tree, void(*)() func, int direction)
Definition: avl.c:483
avl_node ** nodelist
Definition: avl.h:57
static int do_check_tree()
static rotate_left()
avl_node * root
Definition: avl.h:47
#define NIL(type)
Definition: avl.h:25
#define COMPARE(key, nodekey, compare)
Definition: avl.c:31
avl_last(avl_tree *tree, char **key_p, char **value_p)
Definition: avl.c:111
#define ALLOC(type, num)
Definition: avl.h:27
static void do_rebalance()
static void free_entry(avl_node *node, void(*)() key_free, void(*)() value_free)
Definition: avl.c:500
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
#define compute_height(node)
Definition: avl.c:26
#define FREE(obj)
Definition: avl.h:31
int(* compar)()
Definition: avl.h:48
avl_gen(avl_generator *gen, char **key_p, char **value_p)
Definition: avl.c:314
char * value
Definition: avl.h:40
#define MAX(a, b)
Definition: avl.h:23
static rotate_right()
#define BALANCE(node)
Definition: avl.c:24
avl_tree * tree
Definition: avl.h:56
avl_tree * avl_init_table(int(*)() compar)
Definition: avl.c:47
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
avl_lookup(avl_tree *tree, char *key, char **value_p)
Definition: avl.c:61
#define HEIGHT(node)
Definition: avl.c:23
avl_first(avl_tree *tree, char **key_p, char **value_p)
Definition: avl.c:85
#define STACK_SIZE
Definition: avl.c:37
static void avl_record_gen_forward(avl_node *node, avl_generator *gen)
Definition: avl.c:259
avl_generator * avl_init_gen(avl_tree *tree, int dir)
Definition: avl.c:287
enum keys key
int avl_check_tree(avl_tree *tree)
Definition: avl.c:560
#define AVL_FORWARD
Definition: avl.h:62
int value
avl_node * left
Definition: avl.h:38
avl_node * right
Definition: avl.h:38
static void avl_walk_backward(avl_node *node, void(*)() func)
Definition: avl.c:469
static avl_node * find_rightmost()
int avl_numcmp(char *x, char *y)
Definition: avl.c:553