1 /* avl.c - routines to implement an avl tree */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
8 * Copyright (c) 1993 Regents of the University of Michigan.
11 * Redistribution and use in source and binary forms are permitted
12 * provided that this notice is preserved and that due credit is given
13 * to the University of Michigan at Ann Arbor. The name of the University
14 * may not be used to endorse or promote products derived from this
15 * software without specific prior written permission. This software
16 * is provided ``as is'' without express or implied warranty.
22 #include <ac/stdlib.h>
25 #define ber_memalloc malloc
26 #define ber_memrealloc realloc
27 #define ber_memfree free
35 #define ROTATERIGHT(x) { \
37 if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
38 (void) fputs("RR error\n", stderr); exit( EXIT_FAILURE ); \
40 tmp = (*(x))->avl_left;\
41 (*(x))->avl_left = tmp->avl_right;\
42 tmp->avl_right = *(x);\
45 #define ROTATELEFT(x) { \
47 if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
48 (void) fputs("RL error\n", stderr); exit( EXIT_FAILURE ); \
50 tmp = (*(x))->avl_right;\
51 (*(x))->avl_right = tmp->avl_left;\
52 tmp->avl_left = *(x);\
57 * ravl_insert - called from avl_insert() to do a recursive insert into
58 * and balance of an avl tree.
66 AVL_CMP fcmp, /* comparison function */
67 AVL_DUP fdup, /* function to call for duplicates */
71 int rc, cmp, tallersub;
75 if ( (*iroot = (Avlnode *) ber_memalloc( sizeof( Avlnode ) ))
79 (*iroot)->avl_left = 0;
80 (*iroot)->avl_right = 0;
82 (*iroot)->avl_data = data;
87 cmp = (*fcmp)( data, (*iroot)->avl_data );
89 /* equal - duplicate name */
92 return( (*fdup)( (*iroot)->avl_data, data ) );
97 rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
100 switch ( (*iroot)->avl_bf ) {
101 case LH : /* left high - balance is restored */
102 (*iroot)->avl_bf = EH;
105 case EH : /* equal height - now right heavy */
106 (*iroot)->avl_bf = RH;
109 case RH : /* right heavy to start - right balance */
110 r = (*iroot)->avl_right;
111 switch ( r->avl_bf ) {
112 case LH : /* double rotation left */
114 switch ( l->avl_bf ) {
115 case LH : (*iroot)->avl_bf = EH;
118 case EH : (*iroot)->avl_bf = EH;
121 case RH : (*iroot)->avl_bf = LH;
127 (*iroot)->avl_right = r;
131 case EH : /* This should never happen */
133 case RH : /* single rotation left */
134 (*iroot)->avl_bf = EH;
148 rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
151 switch ( (*iroot)->avl_bf ) {
152 case LH : /* left high to start - left balance */
153 l = (*iroot)->avl_left;
154 switch ( l->avl_bf ) {
155 case LH : /* single rotation right */
156 (*iroot)->avl_bf = EH;
161 case EH : /* this should never happen */
163 case RH : /* double rotation right */
165 switch ( r->avl_bf ) {
166 case LH : (*iroot)->avl_bf = RH;
169 case EH : (*iroot)->avl_bf = EH;
172 case RH : (*iroot)->avl_bf = EH;
178 (*iroot)->avl_left = l;
184 case EH : /* equal height - now left heavy */
185 (*iroot)->avl_bf = LH;
188 case RH : /* right high - balance is restored */
189 (*iroot)->avl_bf = EH;
201 * avl_insert -- insert a node containing data data into the avl tree
202 * with root root. fcmp is a function to call to compare the data portion
203 * of two nodes. it should take two arguments and return <, >, or == 0,
204 * depending on whether its first argument is <, >, or == its second
205 * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
206 * node is inserted. it should return 0, or -1 and its return value
207 * will be the return value from avl_insert in the case of a duplicate node.
208 * the function will be called with the original node's data as its first
209 * argument and with the incoming duplicate node's data as its second
210 * argument. this could be used, for example, to keep a count with each
213 * NOTE: this routine may malloc memory
217 avl_insert( Avlnode **root, void* data, AVL_CMP fcmp, AVL_DUP fdup )
221 return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
225 * right_balance() - called from delete when root's right subtree has
226 * been shortened because of a deletion.
230 right_balance( Avlnode **root )
235 switch( (*root)->avl_bf ) {
236 case RH: /* was right high - equal now */
237 (*root)->avl_bf = EH;
240 case EH: /* was equal - left high now */
241 (*root)->avl_bf = LH;
244 case LH: /* was right high - balance */
245 l = (*root)->avl_left;
246 switch ( l->avl_bf ) {
247 case RH : /* double rotation left */
249 switch ( r->avl_bf ) {
251 (*root)->avl_bf = EH;
255 (*root)->avl_bf = EH;
259 (*root)->avl_bf = RH;
265 (*root)->avl_left = l;
269 case EH : /* right rotation */
270 (*root)->avl_bf = LH;
275 case LH : /* single rotation right */
276 (*root)->avl_bf = EH;
289 * left_balance() - called from delete when root's left subtree has
290 * been shortened because of a deletion.
294 left_balance( Avlnode **root )
299 switch( (*root)->avl_bf ) {
300 case LH: /* was left high - equal now */
301 (*root)->avl_bf = EH;
304 case EH: /* was equal - right high now */
305 (*root)->avl_bf = RH;
308 case RH: /* was right high - balance */
309 r = (*root)->avl_right;
310 switch ( r->avl_bf ) {
311 case LH : /* double rotation left */
313 switch ( l->avl_bf ) {
315 (*root)->avl_bf = EH;
319 (*root)->avl_bf = EH;
323 (*root)->avl_bf = LH;
329 (*root)->avl_right = r;
333 case EH : /* single rotation left */
334 (*root)->avl_bf = RH;
339 case RH : /* single rotation left */
340 (*root)->avl_bf = EH;
353 * ravl_delete() - called from avl_delete to do recursive deletion of a
354 * node from an avl tree. It finds the node recursively, deletes it,
355 * and returns shorter if the tree is shorter after the deletion and
360 ravl_delete( Avlnode **root, void* data, AVL_CMP fcmp, int *shorter )
362 int shortersubtree = 0;
365 Avlnode *minnode, *savenode;
367 if ( *root == NULLAVL )
370 cmp = (*fcmp)( data, (*root)->avl_data );
375 savedata = savenode->avl_data;
377 /* simple cases: no left child */
378 if ( (*root)->avl_left == 0 ) {
379 *root = (*root)->avl_right;
381 ber_memfree( (char *) savenode );
384 } else if ( (*root)->avl_right == 0 ) {
385 *root = (*root)->avl_left;
387 ber_memfree( (char *) savenode );
392 * avl_getmin will return to us the smallest node greater
393 * than the one we are trying to delete. deleting this node
394 * from the right subtree is guaranteed to end in one of the
395 * simple cases above.
398 minnode = (*root)->avl_right;
399 while ( minnode->avl_left != NULLAVL )
400 minnode = minnode->avl_left;
403 (*root)->avl_data = minnode->avl_data;
404 minnode->avl_data = savedata;
406 savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
409 if ( shortersubtree )
410 *shorter = right_balance( root );
414 } else if ( cmp < 0 ) {
415 if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
416 &shortersubtree )) == 0 ) {
421 /* left subtree shorter? */
422 if ( shortersubtree )
423 *shorter = left_balance( root );
428 if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
429 &shortersubtree )) == 0 ) {
434 if ( shortersubtree )
435 *shorter = right_balance( root );
444 * avl_delete() - deletes the node containing data (according to fcmp) from
445 * the avl tree rooted at root.
449 avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
453 return( ravl_delete( root, data, fcmp, &shorter ) );
457 avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
460 return( AVL_NOMORE );
462 if ( root->avl_left != 0 )
463 if ( avl_inapply( root->avl_left, fn, arg, stopflag )
467 if ( (*fn)( root->avl_data, arg ) == stopflag )
470 if ( root->avl_right == 0 )
471 return( AVL_NOMORE );
473 return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
477 avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
480 return( AVL_NOMORE );
482 if ( root->avl_left != 0 )
483 if ( avl_postapply( root->avl_left, fn, arg, stopflag )
487 if ( root->avl_right != 0 )
488 if ( avl_postapply( root->avl_right, fn, arg, stopflag )
492 return( (*fn)( root->avl_data, arg ) );
496 avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
499 return( AVL_NOMORE );
501 if ( (*fn)( root->avl_data, arg ) == stopflag )
504 if ( root->avl_left != 0 )
505 if ( avl_preapply( root->avl_left, fn, arg, stopflag )
509 if ( root->avl_right == 0 )
510 return( AVL_NOMORE );
512 return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
516 * avl_apply -- avl tree root is traversed, function fn is called with
517 * arguments arg and the data portion of each node. if fn returns stopflag,
518 * the traversal is cut short, otherwise it continues. Do not use -6 as
519 * a stopflag, as this is what is used to indicate the traversal ran out
524 avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
528 return( avl_inapply( root, fn, arg, stopflag ) );
530 return( avl_preapply( root, fn, arg, stopflag ) );
532 return( avl_postapply( root, fn, arg, stopflag ) );
534 fprintf( stderr, "Invalid traversal type %d\n", type );
542 * avl_prefixapply - traverse avl tree root, applying function fprefix
543 * to any nodes that match. fcmp is called with data as its first arg
544 * and the current node's data as its second arg. it should return
545 * 0 if they match, < 0 if data is less, and > 0 if data is greater.
546 * the idea is to efficiently find all nodes that are prefixes of
547 * some key... Like avl_apply, this routine also takes a stopflag
548 * and will return prematurely if fmatch returns this value. Otherwise,
549 * AVL_NOMORE is returned.
566 return( AVL_NOMORE );
568 cmp = (*fcmp)( data, root->avl_data /* , carg */);
570 if ( (*fmatch)( root->avl_data, marg ) == stopflag )
573 if ( root->avl_left != 0 )
574 if ( avl_prefixapply( root->avl_left, data, fmatch,
575 marg, fcmp, carg, stopflag ) == stopflag )
578 if ( root->avl_right != 0 )
579 return( avl_prefixapply( root->avl_right, data, fmatch,
580 marg, fcmp, carg, stopflag ) );
582 return( AVL_NOMORE );
584 } else if ( cmp < 0 ) {
585 if ( root->avl_left != 0 )
586 return( avl_prefixapply( root->avl_left, data, fmatch,
587 marg, fcmp, carg, stopflag ) );
589 if ( root->avl_right != 0 )
590 return( avl_prefixapply( root->avl_right, data, fmatch,
591 marg, fcmp, carg, stopflag ) );
594 return( AVL_NOMORE );
598 * avl_free -- traverse avltree root, freeing the memory it is using.
599 * the dfree() is called to free the data portion of each node. The
600 * number of items actually freed is returned.
604 avl_free( Avlnode *root, AVL_FREE dfree )
612 if ( root->avl_left != 0 )
613 nleft = avl_free( root->avl_left, dfree );
615 if ( root->avl_right != 0 )
616 nright = avl_free( root->avl_right, dfree );
619 (*dfree)( root->avl_data );
622 return( nleft + nright + 1 );
626 * avl_find -- search avltree root for a node with data data. the function
627 * cmp is used to compare things. it is called with data as its first arg
628 * and the current node data as its second. it should return 0 if they match,
629 * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
633 avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
637 while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
639 root = root->avl_left;
641 root = root->avl_right;
644 return( root ? root->avl_data : 0 );
648 * avl_find_lin -- search avltree root linearly for a node with data data.
649 * the function cmp is used to compare things. it is called with data as its
650 * first arg and the current node data as its second. it should return 0 if
651 * they match, non-zero otherwise.
655 avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
662 if ( (*fcmp)( data, root->avl_data ) == 0 )
663 return( root->avl_data );
665 if ( root->avl_left != 0 )
666 if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
670 if ( root->avl_right == 0 )
673 return( avl_find_lin( root->avl_right, data, fcmp ) );
676 /* NON-REENTRANT INTERFACE */
678 static void* *avl_list;
679 static int avl_maxlist;
680 static int avl_nextlist;
682 #define AVL_GRABSIZE 100
686 avl_buildlist( void* data, void* arg )
690 if ( avl_list == (void* *) 0 ) {
691 avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*));
692 slots = AVL_GRABSIZE;
694 } else if ( avl_maxlist == slots ) {
695 slots += AVL_GRABSIZE;
696 avl_list = (void* *) ber_memrealloc( (char *) avl_list,
697 (unsigned) slots * sizeof(void*));
700 avl_list[ avl_maxlist++ ] = data;
706 * avl_getfirst() and avl_getnext() are provided as alternate tree
707 * traversal methods, to be used when a single function cannot be
708 * provided to be called with every node in the tree. avl_getfirst()
709 * traverses the tree and builds a linear list of all the nodes,
710 * returning the first node. avl_getnext() returns the next thing
711 * on the list built by avl_getfirst(). This means that avl_getfirst()
712 * can take a while, and that the tree should not be messed with while
713 * being traversed in this way, and that multiple traversals (even of
714 * different trees) cannot be active at once.
718 avl_getfirst( Avlnode *root )
721 ber_memfree( (char *) avl_list);
722 avl_list = (void* *) 0;
730 (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
732 return( avl_list[ avl_nextlist++ ] );
741 if ( avl_nextlist == avl_maxlist ) {
742 ber_memfree( (void*) avl_list);
743 avl_list = (void* *) 0;
747 return( avl_list[ avl_nextlist++ ] );
750 /* end non-reentrant code */
754 avl_dup_error( void* left, void* right )
760 avl_dup_ok( void* left, void* right )