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.
15 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
16 static char avl_version[] = "AVL library version 1.0\n";
19 #include <sys/types.h>
24 #define ROTATERIGHT(x) { \
26 if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
27 (void) printf("RR error\n"); exit(1); \
29 tmp = (*(x))->avl_left;\
30 (*(x))->avl_left = tmp->avl_right;\
31 tmp->avl_right = *(x);\
34 #define ROTATELEFT(x) { \
36 if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
37 (void) printf("RL error\n"); exit(1); \
39 tmp = (*(x))->avl_right;\
40 (*(x))->avl_right = tmp->avl_left;\
46 * ravl_insert - called from avl_insert() to do a recursive insert into
47 * and balance of an avl tree.
51 int ravl_insert( iroot, data, taller, fcmp, fdup, depth )
55 IFP fcmp; /* comparison function */
56 IFP fdup; /* function to call for duplicates */
59 int rc, cmp, tallersub;
63 if ( (*iroot = (Avlnode *) malloc( sizeof( Avlnode ) ))
67 (*iroot)->avl_left = 0;
68 (*iroot)->avl_right = 0;
70 (*iroot)->avl_data = data;
75 cmp = (*fcmp)( data, (*iroot)->avl_data );
77 /* equal - duplicate name */
80 return( (*fdup)( (*iroot)->avl_data, data ) );
85 rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
88 switch ( (*iroot)->avl_bf ) {
89 case LH : /* left high - balance is restored */
90 (*iroot)->avl_bf = EH;
93 case EH : /* equal height - now right heavy */
94 (*iroot)->avl_bf = RH;
97 case RH : /* right heavy to start - right balance */
98 r = (*iroot)->avl_right;
99 switch ( r->avl_bf ) {
100 case LH : /* double rotation left */
102 switch ( l->avl_bf ) {
103 case LH : (*iroot)->avl_bf = EH;
106 case EH : (*iroot)->avl_bf = EH;
109 case RH : (*iroot)->avl_bf = LH;
115 (*iroot)->avl_right = r;
119 case EH : /* This should never happen */
121 case RH : /* single rotation left */
122 (*iroot)->avl_bf = EH;
136 rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
139 switch ( (*iroot)->avl_bf ) {
140 case LH : /* left high to start - left balance */
141 l = (*iroot)->avl_left;
142 switch ( l->avl_bf ) {
143 case LH : /* single rotation right */
144 (*iroot)->avl_bf = EH;
149 case EH : /* this should never happen */
151 case RH : /* double rotation right */
153 switch ( r->avl_bf ) {
154 case LH : (*iroot)->avl_bf = RH;
157 case EH : (*iroot)->avl_bf = EH;
160 case RH : (*iroot)->avl_bf = EH;
166 (*iroot)->avl_left = l;
172 case EH : /* equal height - now left heavy */
173 (*iroot)->avl_bf = LH;
176 case RH : /* right high - balance is restored */
177 (*iroot)->avl_bf = EH;
189 * avl_insert -- insert a node containing data data into the avl tree
190 * with root root. fcmp is a function to call to compare the data portion
191 * of two nodes. it should take two arguments and return <, >, or == 0,
192 * depending on whether its first argument is <, >, or == its second
193 * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
194 * node is inserted. it should return 0, or -1 and its return value
195 * will be the return value from avl_insert in the case of a duplicate node.
196 * the function will be called with the original node's data as its first
197 * argument and with the incoming duplicate node's data as its second
198 * argument. this could be used, for example, to keep a count with each
201 * NOTE: this routine may malloc memory
204 int avl_insert( root, data, fcmp, fdup )
212 return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
216 * right_balance() - called from delete when root's right subtree has
217 * been shortened because of a deletion.
221 right_balance( 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 int left_balance( root )
292 switch( (*root)->avl_bf ) {
293 case LH: /* was left high - equal now */
294 (*root)->avl_bf = EH;
297 case EH: /* was equal - right high now */
298 (*root)->avl_bf = RH;
301 case RH: /* was right high - balance */
302 r = (*root)->avl_right;
303 switch ( r->avl_bf ) {
304 case LH : /* double rotation left */
306 switch ( l->avl_bf ) {
308 (*root)->avl_bf = EH;
312 (*root)->avl_bf = EH;
316 (*root)->avl_bf = LH;
322 (*root)->avl_right = r;
326 case EH : /* single rotation left */
327 (*root)->avl_bf = RH;
332 case RH : /* single rotation left */
333 (*root)->avl_bf = EH;
346 * ravl_delete() - called from avl_delete to do recursive deletion of a
347 * node from an avl tree. It finds the node recursively, deletes it,
348 * and returns shorter if the tree is shorter after the deletion and
353 ravl_delete( root, data, fcmp, shorter )
359 int shortersubtree = 0;
362 Avlnode *minnode, *savenode;
364 if ( *root == NULLAVL )
367 cmp = (*fcmp)( data, (*root)->avl_data );
372 savedata = savenode->avl_data;
374 /* simple cases: no left child */
375 if ( (*root)->avl_left == 0 ) {
376 *root = (*root)->avl_right;
378 free( (char *) savenode );
381 } else if ( (*root)->avl_right == 0 ) {
382 *root = (*root)->avl_left;
384 free( (char *) savenode );
389 * avl_getmin will return to us the smallest node greater
390 * than the one we are trying to delete. deleting this node
391 * from the right subtree is guaranteed to end in one of the
392 * simple cases above.
395 minnode = (*root)->avl_right;
396 while ( minnode->avl_left != NULLAVL )
397 minnode = minnode->avl_left;
400 (*root)->avl_data = minnode->avl_data;
401 minnode->avl_data = savedata;
403 savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
406 if ( shortersubtree )
407 *shorter = right_balance( root );
411 } else if ( cmp < 0 ) {
412 if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
413 &shortersubtree )) == 0 ) {
418 /* left subtree shorter? */
419 if ( shortersubtree )
420 *shorter = left_balance( root );
425 if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
426 &shortersubtree )) == 0 ) {
431 if ( shortersubtree )
432 *shorter = right_balance( root );
441 * avl_delete() - deletes the node containing data (according to fcmp) from
442 * the avl tree rooted at root.
446 avl_delete( root, data, fcmp )
453 return( ravl_delete( root, data, fcmp, &shorter ) );
457 int avl_inapply( root, fn, arg, stopflag )
464 return( AVL_NOMORE );
466 if ( root->avl_left != 0 )
467 if ( avl_inapply( root->avl_left, fn, arg, stopflag )
471 if ( (*fn)( root->avl_data, arg ) == stopflag )
474 if ( root->avl_right == 0 )
475 return( AVL_NOMORE );
477 return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
481 int avl_postapply( root, fn, arg, stopflag )
488 return( AVL_NOMORE );
490 if ( root->avl_left != 0 )
491 if ( avl_postapply( root->avl_left, fn, arg, stopflag )
495 if ( root->avl_right != 0 )
496 if ( avl_postapply( root->avl_right, fn, arg, stopflag )
500 return( (*fn)( root->avl_data, arg ) );
504 int avl_preapply( root, fn, arg, stopflag )
511 return( AVL_NOMORE );
513 if ( (*fn)( root->avl_data, arg ) == stopflag )
516 if ( root->avl_left != 0 )
517 if ( avl_preapply( root->avl_left, fn, arg, stopflag )
521 if ( root->avl_right == 0 )
522 return( AVL_NOMORE );
524 return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
528 * avl_apply -- avl tree root is traversed, function fn is called with
529 * arguments arg and the data portion of each node. if fn returns stopflag,
530 * the traversal is cut short, otherwise it continues. Do not use -6 as
531 * a stopflag, as this is what is used to indicate the traversal ran out
535 int avl_apply( root, fn, arg, stopflag, type )
544 return( avl_inapply( root, fn, arg, stopflag ) );
546 return( avl_preapply( root, fn, arg, stopflag ) );
548 return( avl_postapply( root, fn, arg, stopflag ) );
550 fprintf( stderr, "Invalid traversal type %d\n", type );
558 * avl_prefixapply - traverse avl tree root, applying function fprefix
559 * to any nodes that match. fcmp is called with data as its first arg
560 * and the current node's data as its second arg. it should return
561 * 0 if they match, < 0 if data is less, and > 0 if data is greater.
562 * the idea is to efficiently find all nodes that are prefixes of
563 * some key... Like avl_apply, this routine also takes a stopflag
564 * and will return prematurely if fmatch returns this value. Otherwise,
565 * AVL_NOMORE is returned.
568 int avl_prefixapply( root, data, fmatch, marg, fcmp, carg, stopflag )
580 return( AVL_NOMORE );
582 cmp = (*fcmp)( data, root->avl_data, carg );
584 if ( (*fmatch)( root->avl_data, marg ) == stopflag )
587 if ( root->avl_left != 0 )
588 if ( avl_prefixapply( root->avl_left, data, fmatch,
589 marg, fcmp, carg, stopflag ) == stopflag )
592 if ( root->avl_right != 0 )
593 return( avl_prefixapply( root->avl_right, data, fmatch,
594 marg, fcmp, carg, stopflag ) );
596 return( AVL_NOMORE );
598 } else if ( cmp < 0 ) {
599 if ( root->avl_left != 0 )
600 return( avl_prefixapply( root->avl_left, data, fmatch,
601 marg, fcmp, carg, stopflag ) );
603 if ( root->avl_right != 0 )
604 return( avl_prefixapply( root->avl_right, data, fmatch,
605 marg, fcmp, carg, stopflag ) );
608 return( AVL_NOMORE );
612 * avl_free -- traverse avltree root, freeing the memory it is using.
613 * the dfree() is called to free the data portion of each node. The
614 * number of items actually freed is returned.
617 int avl_free( root, dfree )
627 if ( root->avl_left != 0 )
628 nleft = avl_free( root->avl_left, dfree );
630 if ( root->avl_right != 0 )
631 nright = avl_free( root->avl_right, dfree );
634 (*dfree)( root->avl_data );
636 return( nleft + nright + 1 );
640 * avl_find -- search avltree root for a node with data data. the function
641 * cmp is used to compare things. it is called with data as its first arg
642 * and the current node data as its second. it should return 0 if they match,
643 * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
647 avl_find( root, data, fcmp )
654 while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
656 root = root->avl_left;
658 root = root->avl_right;
661 return( root ? root->avl_data : 0 );
665 * avl_find_lin -- search avltree root linearly for a node with data data.
666 * the function cmp is used to compare things. it is called with data as its
667 * first arg and the current node data as its second. it should return 0 if
668 * they match, non-zero otherwise.
672 avl_find_lin( root, data, fcmp )
682 if ( (*fcmp)( data, root->avl_data ) == 0 )
683 return( root->avl_data );
685 if ( root->avl_left != 0 )
686 if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
690 if ( root->avl_right == 0 )
693 return( avl_find_lin( root->avl_right, data, fcmp ) );
696 static caddr_t *avl_list;
697 static int avl_maxlist;
698 static int avl_nextlist;
700 #define AVL_GRABSIZE 100
704 int avl_buildlist( data, arg )
710 if ( avl_list == (caddr_t *) 0 ) {
711 avl_list = (caddr_t *) malloc(AVL_GRABSIZE * sizeof(caddr_t));
712 slots = AVL_GRABSIZE;
714 } else if ( avl_maxlist == slots ) {
715 slots += AVL_GRABSIZE;
716 avl_list = (caddr_t *) realloc( (char *) avl_list,
717 (unsigned) slots * sizeof(caddr_t));
720 avl_list[ avl_maxlist++ ] = data;
726 * avl_getfirst() and avl_getnext() are provided as alternate tree
727 * traversal methods, to be used when a single function cannot be
728 * provided to be called with every node in the tree. avl_getfirst()
729 * traverses the tree and builds a linear list of all the nodes,
730 * returning the first node. avl_getnext() returns the next thing
731 * on the list built by avl_getfirst(). This means that avl_getfirst()
732 * can take a while, and that the tree should not be messed with while
733 * being traversed in this way, and that multiple traversals (even of
734 * different trees) cannot be active at once.
742 free( (char *) avl_list);
743 avl_list = (caddr_t *) 0;
751 (void) avl_apply( root, avl_buildlist, (caddr_t) 0, -1, AVL_INORDER );
753 return( avl_list[ avl_nextlist++ ] );
762 if ( avl_nextlist == avl_maxlist ) {
763 free( (caddr_t) avl_list);
764 avl_list = (caddr_t *) 0;
768 return( avl_list[ avl_nextlist++ ] );