1 /* avl.c - routines to implement an avl tree */
3 * Copyright (c) 1993 Regents of the University of Michigan.
6 * Redistribution and use in source and binary forms are permitted
7 * provided that this notice is preserved and that due credit is given
8 * to the University of Michigan at Ann Arbor. The name of the University
9 * may not be used to endorse or promote products derived from this
10 * software without specific prior written permission. This software
11 * is provided ``as is'' without express or implied warranty.
17 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
18 static char avl_version[] = "AVL library version 1.0\n";
22 #include <ac/stdlib.h>
27 #define ROTATERIGHT(x) { \
29 if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
30 (void) fputs("RR error\n", stderr); exit(1); \
32 tmp = (*(x))->avl_left;\
33 (*(x))->avl_left = tmp->avl_right;\
34 tmp->avl_right = *(x);\
37 #define ROTATELEFT(x) { \
39 if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
40 (void) fputs("RL error\n", stderr); exit(1); \
42 tmp = (*(x))->avl_right;\
43 (*(x))->avl_right = tmp->avl_left;\
44 tmp->avl_left = *(x);\
49 * ravl_insert - called from avl_insert() to do a recursive insert into
50 * and balance of an avl tree.
58 AVL_CMP fcmp, /* comparison function */
59 AVL_DUP fdup, /* function to call for duplicates */
63 int rc, cmp, tallersub;
67 if ( (*iroot = (Avlnode *) malloc( sizeof( Avlnode ) ))
71 (*iroot)->avl_left = 0;
72 (*iroot)->avl_right = 0;
74 (*iroot)->avl_data = data;
79 cmp = (*fcmp)( data, (*iroot)->avl_data );
81 /* equal - duplicate name */
84 return( (*fdup)( (*iroot)->avl_data, data ) );
89 rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
92 switch ( (*iroot)->avl_bf ) {
93 case LH : /* left high - balance is restored */
94 (*iroot)->avl_bf = EH;
97 case EH : /* equal height - now right heavy */
98 (*iroot)->avl_bf = RH;
101 case RH : /* right heavy to start - right balance */
102 r = (*iroot)->avl_right;
103 switch ( r->avl_bf ) {
104 case LH : /* double rotation left */
106 switch ( l->avl_bf ) {
107 case LH : (*iroot)->avl_bf = EH;
110 case EH : (*iroot)->avl_bf = EH;
113 case RH : (*iroot)->avl_bf = LH;
119 (*iroot)->avl_right = r;
123 case EH : /* This should never happen */
125 case RH : /* single rotation left */
126 (*iroot)->avl_bf = EH;
140 rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
143 switch ( (*iroot)->avl_bf ) {
144 case LH : /* left high to start - left balance */
145 l = (*iroot)->avl_left;
146 switch ( l->avl_bf ) {
147 case LH : /* single rotation right */
148 (*iroot)->avl_bf = EH;
153 case EH : /* this should never happen */
155 case RH : /* double rotation right */
157 switch ( r->avl_bf ) {
158 case LH : (*iroot)->avl_bf = RH;
161 case EH : (*iroot)->avl_bf = EH;
164 case RH : (*iroot)->avl_bf = EH;
170 (*iroot)->avl_left = l;
176 case EH : /* equal height - now left heavy */
177 (*iroot)->avl_bf = LH;
180 case RH : /* right high - balance is restored */
181 (*iroot)->avl_bf = EH;
193 * avl_insert -- insert a node containing data data into the avl tree
194 * with root root. fcmp is a function to call to compare the data portion
195 * of two nodes. it should take two arguments and return <, >, or == 0,
196 * depending on whether its first argument is <, >, or == its second
197 * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
198 * node is inserted. it should return 0, or -1 and its return value
199 * will be the return value from avl_insert in the case of a duplicate node.
200 * the function will be called with the original node's data as its first
201 * argument and with the incoming duplicate node's data as its second
202 * argument. this could be used, for example, to keep a count with each
205 * NOTE: this routine may malloc memory
209 avl_insert( Avlnode **root, void* data, AVL_CMP fcmp, AVL_DUP fdup )
213 return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
217 * right_balance() - called from delete when root's right subtree has
218 * been shortened because of a deletion.
222 right_balance( Avlnode **root )
227 switch( (*root)->avl_bf ) {
228 case RH: /* was right high - equal now */
229 (*root)->avl_bf = EH;
232 case EH: /* was equal - left high now */
233 (*root)->avl_bf = LH;
236 case LH: /* was right high - balance */
237 l = (*root)->avl_left;
238 switch ( l->avl_bf ) {
239 case RH : /* double rotation left */
241 switch ( r->avl_bf ) {
243 (*root)->avl_bf = EH;
247 (*root)->avl_bf = EH;
251 (*root)->avl_bf = RH;
257 (*root)->avl_left = l;
261 case EH : /* right rotation */
262 (*root)->avl_bf = LH;
267 case LH : /* single rotation right */
268 (*root)->avl_bf = EH;
281 * left_balance() - called from delete when root's left subtree has
282 * been shortened because of a deletion.
286 left_balance( Avlnode **root )
291 switch( (*root)->avl_bf ) {
292 case LH: /* was left high - equal now */
293 (*root)->avl_bf = EH;
296 case EH: /* was equal - right high now */
297 (*root)->avl_bf = RH;
300 case RH: /* was right high - balance */
301 r = (*root)->avl_right;
302 switch ( r->avl_bf ) {
303 case LH : /* double rotation left */
305 switch ( l->avl_bf ) {
307 (*root)->avl_bf = EH;
311 (*root)->avl_bf = EH;
315 (*root)->avl_bf = LH;
321 (*root)->avl_right = r;
325 case EH : /* single rotation left */
326 (*root)->avl_bf = RH;
331 case RH : /* single rotation left */
332 (*root)->avl_bf = EH;
345 * ravl_delete() - called from avl_delete to do recursive deletion of a
346 * node from an avl tree. It finds the node recursively, deletes it,
347 * and returns shorter if the tree is shorter after the deletion and
352 ravl_delete( Avlnode **root, void* data, AVL_CMP fcmp, int *shorter )
354 int shortersubtree = 0;
357 Avlnode *minnode, *savenode;
359 if ( *root == NULLAVL )
362 cmp = (*fcmp)( data, (*root)->avl_data );
367 savedata = savenode->avl_data;
369 /* simple cases: no left child */
370 if ( (*root)->avl_left == 0 ) {
371 *root = (*root)->avl_right;
373 free( (char *) savenode );
376 } else if ( (*root)->avl_right == 0 ) {
377 *root = (*root)->avl_left;
379 free( (char *) savenode );
384 * avl_getmin will return to us the smallest node greater
385 * than the one we are trying to delete. deleting this node
386 * from the right subtree is guaranteed to end in one of the
387 * simple cases above.
390 minnode = (*root)->avl_right;
391 while ( minnode->avl_left != NULLAVL )
392 minnode = minnode->avl_left;
395 (*root)->avl_data = minnode->avl_data;
396 minnode->avl_data = savedata;
398 savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
401 if ( shortersubtree )
402 *shorter = right_balance( root );
406 } else if ( cmp < 0 ) {
407 if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
408 &shortersubtree )) == 0 ) {
413 /* left subtree shorter? */
414 if ( shortersubtree )
415 *shorter = left_balance( root );
420 if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
421 &shortersubtree )) == 0 ) {
426 if ( shortersubtree )
427 *shorter = right_balance( root );
436 * avl_delete() - deletes the node containing data (according to fcmp) from
437 * the avl tree rooted at root.
441 avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
445 return( ravl_delete( root, data, fcmp, &shorter ) );
449 avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
452 return( AVL_NOMORE );
454 if ( root->avl_left != 0 )
455 if ( avl_inapply( root->avl_left, fn, arg, stopflag )
459 if ( (*fn)( root->avl_data, arg ) == stopflag )
462 if ( root->avl_right == 0 )
463 return( AVL_NOMORE );
465 return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
469 avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
472 return( AVL_NOMORE );
474 if ( root->avl_left != 0 )
475 if ( avl_postapply( root->avl_left, fn, arg, stopflag )
479 if ( root->avl_right != 0 )
480 if ( avl_postapply( root->avl_right, fn, arg, stopflag )
484 return( (*fn)( root->avl_data, arg ) );
488 avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
491 return( AVL_NOMORE );
493 if ( (*fn)( root->avl_data, arg ) == stopflag )
496 if ( root->avl_left != 0 )
497 if ( avl_preapply( root->avl_left, fn, arg, stopflag )
501 if ( root->avl_right == 0 )
502 return( AVL_NOMORE );
504 return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
508 * avl_apply -- avl tree root is traversed, function fn is called with
509 * arguments arg and the data portion of each node. if fn returns stopflag,
510 * the traversal is cut short, otherwise it continues. Do not use -6 as
511 * a stopflag, as this is what is used to indicate the traversal ran out
516 avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
520 return( avl_inapply( root, fn, arg, stopflag ) );
522 return( avl_preapply( root, fn, arg, stopflag ) );
524 return( avl_postapply( root, fn, arg, stopflag ) );
526 fprintf( stderr, "Invalid traversal type %d\n", type );
534 * avl_prefixapply - traverse avl tree root, applying function fprefix
535 * to any nodes that match. fcmp is called with data as its first arg
536 * and the current node's data as its second arg. it should return
537 * 0 if they match, < 0 if data is less, and > 0 if data is greater.
538 * the idea is to efficiently find all nodes that are prefixes of
539 * some key... Like avl_apply, this routine also takes a stopflag
540 * and will return prematurely if fmatch returns this value. Otherwise,
541 * AVL_NOMORE is returned.
558 return( AVL_NOMORE );
560 cmp = (*fcmp)( data, root->avl_data /* , carg */);
562 if ( (*fmatch)( root->avl_data, marg ) == stopflag )
565 if ( root->avl_left != 0 )
566 if ( avl_prefixapply( root->avl_left, data, fmatch,
567 marg, fcmp, carg, stopflag ) == stopflag )
570 if ( root->avl_right != 0 )
571 return( avl_prefixapply( root->avl_right, data, fmatch,
572 marg, fcmp, carg, stopflag ) );
574 return( AVL_NOMORE );
576 } else if ( cmp < 0 ) {
577 if ( root->avl_left != 0 )
578 return( avl_prefixapply( root->avl_left, data, fmatch,
579 marg, fcmp, carg, stopflag ) );
581 if ( root->avl_right != 0 )
582 return( avl_prefixapply( root->avl_right, data, fmatch,
583 marg, fcmp, carg, stopflag ) );
586 return( AVL_NOMORE );
590 * avl_free -- traverse avltree root, freeing the memory it is using.
591 * the dfree() is called to free the data portion of each node. The
592 * number of items actually freed is returned.
596 avl_free( Avlnode *root, AVL_FREE dfree )
604 if ( root->avl_left != 0 )
605 nleft = avl_free( root->avl_left, dfree );
607 if ( root->avl_right != 0 )
608 nright = avl_free( root->avl_right, dfree );
611 (*dfree)( root->avl_data );
614 return( nleft + nright + 1 );
618 * avl_find -- search avltree root for a node with data data. the function
619 * cmp is used to compare things. it is called with data as its first arg
620 * and the current node data as its second. it should return 0 if they match,
621 * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
625 avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
629 while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
631 root = root->avl_left;
633 root = root->avl_right;
636 return( root ? root->avl_data : 0 );
640 * avl_find_lin -- search avltree root linearly for a node with data data.
641 * the function cmp is used to compare things. it is called with data as its
642 * first arg and the current node data as its second. it should return 0 if
643 * they match, non-zero otherwise.
647 avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
654 if ( (*fcmp)( data, root->avl_data ) == 0 )
655 return( root->avl_data );
657 if ( root->avl_left != 0 )
658 if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
662 if ( root->avl_right == 0 )
665 return( avl_find_lin( root->avl_right, data, fcmp ) );
668 /* NON-REENTRANT INTERFACE */
670 static void* *avl_list;
671 static int avl_maxlist;
672 static int avl_nextlist;
674 #define AVL_GRABSIZE 100
678 avl_buildlist( void* data, void* arg )
682 if ( avl_list == (void* *) 0 ) {
683 avl_list = (void* *) malloc(AVL_GRABSIZE * sizeof(void*));
684 slots = AVL_GRABSIZE;
686 } else if ( avl_maxlist == slots ) {
687 slots += AVL_GRABSIZE;
688 avl_list = (void* *) realloc( (char *) avl_list,
689 (unsigned) slots * sizeof(void*));
692 avl_list[ avl_maxlist++ ] = data;
698 * avl_getfirst() and avl_getnext() are provided as alternate tree
699 * traversal methods, to be used when a single function cannot be
700 * provided to be called with every node in the tree. avl_getfirst()
701 * traverses the tree and builds a linear list of all the nodes,
702 * returning the first node. avl_getnext() returns the next thing
703 * on the list built by avl_getfirst(). This means that avl_getfirst()
704 * can take a while, and that the tree should not be messed with while
705 * being traversed in this way, and that multiple traversals (even of
706 * different trees) cannot be active at once.
710 avl_getfirst( Avlnode *root )
713 free( (char *) avl_list);
714 avl_list = (void* *) 0;
722 (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
724 return( avl_list[ avl_nextlist++ ] );
733 if ( avl_nextlist == avl_maxlist ) {
734 free( (void*) avl_list);
735 avl_list = (void* *) 0;
739 return( avl_list[ avl_nextlist++ ] );
742 /* end non-reentrant code */
746 avl_dup_error( void* left, void* right )
752 avl_dup_ok( void* left, void* right )