ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
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
39static avl_node *new_node ();
40static avl_node *find_rightmost ();
41static void do_rebalance ();
42static rotate_left ();
43static rotate_right ();
44static int do_check_tree ();
45
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
61avl_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
85avl_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
111avl_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
170avl_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
207avl_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
258static void
259avl_record_gen_forward (node, gen)
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
272static void
273avl_record_gen_backward (node, gen)
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
287avl_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
314avl_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
337void
339 avl_generator *gen;
340{
341 FREE (gen->nodelist);
342 FREE (gen);
343}
344
345static avl_node *
346find_rightmost (node_p)
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
367static void
368do_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
401static
402rotate_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
428static
429rotate_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
454static void
455avl_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
468static void
469avl_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
482void
483avl_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
499static void
500free_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
518void
519avl_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
529int
531 avl_tree *tree;
532{
533 return tree->num_entries;
534}
535
536static avl_node *
537new_node (key, value)
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
552int
554 char *x, *y;
555{
556 return (int) x - (int) y;
557}
558
559int
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
569static int
570do_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
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
avl_insert(avl_tree *tree, char *key, char *value)
Definition avl.c:136
void avl_foreach(avl_tree *tree, void *func, int direction)
Definition avl.c:483
int avl_numcmp(char *x, char *y)
Definition avl.c:553
avl_lookup(avl_tree *tree, char *key, char **value_p)
Definition avl.c:61
avl_gen(avl_generator *gen, char **key_p, char **value_p)
Definition avl.c:314
avl_generator * avl_init_gen(avl_tree *tree, int dir)
Definition avl.c:287
void avl_free_table(avl_tree *tree, void *key_free, void *value_free)
Definition avl.c:519
#define STACK_SIZE
Definition avl.c:37
#define HEIGHT(node)
Definition avl.c:23
#define compute_height(node)
Definition avl.c:26
void avl_free_gen(avl_generator *gen)
Definition avl.c:338
#define COMPARE(key, nodekey, compare)
Definition avl.c:31
avl_find_or_add(avl_tree *tree, char *key, char ***slot_p)
Definition avl.c:170
avl_delete(avl_tree *tree, char **key_p, char **value_p)
Definition avl.c:207
avl_tree * avl_init_table(int *compar)
Definition avl.c:47
#define BALANCE(node)
Definition avl.c:24
avl_first(avl_tree *tree, char **key_p, char **value_p)
Definition avl.c:85
int avl_count(avl_tree *tree)
Definition avl.c:530
int avl_check_tree(avl_tree *tree)
Definition avl.c:560
avl_last(avl_tree *tree, char **key_p, char **value_p)
Definition avl.c:111
struct avl_generator_struct avl_generator
Definition avl.h:54
#define ALLOC(type, num)
Definition avl.h:27
#define AVL_FORWARD
Definition avl.h:62
#define NIL(type)
Definition avl.h:25
struct avl_tree_struct avl_tree
Definition avl.h:45
struct avl_node_struct avl_node
Definition avl.h:36
#define FREE(obj)
Definition avl.h:31
#define MAX(a, b)
Definition avl.h:23
ABC_NAMESPACE_IMPL_START typedef signed char value
enum keys key
Definition main.h:25
avl_node ** nodelist
Definition avl.h:57
avl_tree * tree
Definition avl.h:56
char * key
Definition avl.h:39
int height
Definition avl.h:41
char * value
Definition avl.h:40
avl_node * left
Definition avl.h:38
avl_node * right
Definition avl.h:38
avl_node * root
Definition avl.h:47
int num_entries
Definition avl.h:49
int modified
Definition avl.h:50
int(* compar)()
Definition avl.h:48