1 /* avl.c - routines to implement an avl tree */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1993 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
27 * This work was originally developed by the University of Michigan
28 * (as part of U-MICH LDAP). Additional significant contributors
30 * Hallvard B. Furuseth
37 #include <ac/stdlib.h>
40 #define ber_memalloc malloc
41 #define ber_memrealloc realloc
42 #define ber_memfree free
50 #define ROTATERIGHT(x) { \
52 if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
53 (void) fputs("RR error\n", stderr); exit( EXIT_FAILURE ); \
55 tmp = (*(x))->avl_left;\
56 (*(x))->avl_left = tmp->avl_right;\
57 tmp->avl_right = *(x);\
60 #define ROTATELEFT(x) { \
62 if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
63 (void) fputs("RL error\n", stderr); exit( EXIT_FAILURE ); \
65 tmp = (*(x))->avl_right;\
66 (*(x))->avl_right = tmp->avl_left;\
67 tmp->avl_left = *(x);\
72 * ravl_insert - called from avl_insert() to do a recursive insert into
73 * and balance of an avl tree.
81 AVL_CMP fcmp, /* comparison function */
82 AVL_DUP fdup, /* function to call for duplicates */
86 int rc, cmp, tallersub;
90 if ( (*iroot = (Avlnode *) ber_memalloc( sizeof( Avlnode ) ))
94 (*iroot)->avl_left = 0;
95 (*iroot)->avl_right = 0;
97 (*iroot)->avl_data = data;
102 cmp = (*fcmp)( data, (*iroot)->avl_data );
104 /* equal - duplicate name */
107 return( (*fdup)( (*iroot)->avl_data, data ) );
111 else if ( cmp > 0 ) {
112 rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
115 switch ( (*iroot)->avl_bf ) {
116 case LH : /* left high - balance is restored */
117 (*iroot)->avl_bf = EH;
120 case EH : /* equal height - now right heavy */
121 (*iroot)->avl_bf = RH;
124 case RH : /* right heavy to start - right balance */
125 r = (*iroot)->avl_right;
126 switch ( r->avl_bf ) {
127 case LH : /* double rotation left */
129 switch ( l->avl_bf ) {
130 case LH : (*iroot)->avl_bf = EH;
133 case EH : (*iroot)->avl_bf = EH;
136 case RH : (*iroot)->avl_bf = LH;
142 (*iroot)->avl_right = r;
146 case EH : /* This should never happen */
148 case RH : /* single rotation left */
149 (*iroot)->avl_bf = EH;
163 rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
166 switch ( (*iroot)->avl_bf ) {
167 case LH : /* left high to start - left balance */
168 l = (*iroot)->avl_left;
169 switch ( l->avl_bf ) {
170 case LH : /* single rotation right */
171 (*iroot)->avl_bf = EH;
176 case EH : /* this should never happen */
178 case RH : /* double rotation right */
180 switch ( r->avl_bf ) {
181 case LH : (*iroot)->avl_bf = RH;
184 case EH : (*iroot)->avl_bf = EH;
187 case RH : (*iroot)->avl_bf = EH;
193 (*iroot)->avl_left = l;
199 case EH : /* equal height - now left heavy */
200 (*iroot)->avl_bf = LH;
203 case RH : /* right high - balance is restored */
204 (*iroot)->avl_bf = EH;
216 * avl_insert -- insert a node containing data data into the avl tree
217 * with root root. fcmp is a function to call to compare the data portion
218 * of two nodes. it should take two arguments and return <, >, or == 0,
219 * depending on whether its first argument is <, >, or == its second
220 * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
221 * node is inserted. it should return 0, or -1 and its return value
222 * will be the return value from avl_insert in the case of a duplicate node.
223 * the function will be called with the original node's data as its first
224 * argument and with the incoming duplicate node's data as its second
225 * argument. this could be used, for example, to keep a count with each
228 * NOTE: this routine may malloc memory
232 avl_insert( Avlnode **root, void* data, AVL_CMP fcmp, AVL_DUP fdup )
236 return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
240 * right_balance() - called from delete when root's right subtree has
241 * been shortened because of a deletion.
245 right_balance( Avlnode **root )
250 switch( (*root)->avl_bf ) {
251 case RH: /* was right high - equal now */
252 (*root)->avl_bf = EH;
255 case EH: /* was equal - left high now */
256 (*root)->avl_bf = LH;
259 case LH: /* was right high - balance */
260 l = (*root)->avl_left;
261 switch ( l->avl_bf ) {
262 case RH : /* double rotation left */
264 switch ( r->avl_bf ) {
266 (*root)->avl_bf = EH;
270 (*root)->avl_bf = EH;
274 (*root)->avl_bf = RH;
280 (*root)->avl_left = l;
284 case EH : /* right rotation */
285 (*root)->avl_bf = LH;
290 case LH : /* single rotation right */
291 (*root)->avl_bf = EH;
304 * left_balance() - called from delete when root's left subtree has
305 * been shortened because of a deletion.
309 left_balance( Avlnode **root )
314 switch( (*root)->avl_bf ) {
315 case LH: /* was left high - equal now */
316 (*root)->avl_bf = EH;
319 case EH: /* was equal - right high now */
320 (*root)->avl_bf = RH;
323 case RH: /* was right high - balance */
324 r = (*root)->avl_right;
325 switch ( r->avl_bf ) {
326 case LH : /* double rotation left */
328 switch ( l->avl_bf ) {
330 (*root)->avl_bf = EH;
334 (*root)->avl_bf = EH;
338 (*root)->avl_bf = LH;
344 (*root)->avl_right = r;
348 case EH : /* single rotation left */
349 (*root)->avl_bf = RH;
354 case RH : /* single rotation left */
355 (*root)->avl_bf = EH;
368 * ravl_delete() - called from avl_delete to do recursive deletion of a
369 * node from an avl tree. It finds the node recursively, deletes it,
370 * and returns shorter if the tree is shorter after the deletion and
375 ravl_delete( Avlnode **root, void* data, AVL_CMP fcmp, int *shorter )
377 int shortersubtree = 0;
380 Avlnode *minnode, *savenode;
382 if ( *root == NULLAVL )
385 cmp = (*fcmp)( data, (*root)->avl_data );
390 savedata = savenode->avl_data;
392 /* simple cases: no left child */
393 if ( (*root)->avl_left == 0 ) {
394 *root = (*root)->avl_right;
396 ber_memfree( (char *) savenode );
399 } else if ( (*root)->avl_right == 0 ) {
400 *root = (*root)->avl_left;
402 ber_memfree( (char *) savenode );
407 * avl_getmin will return to us the smallest node greater
408 * than the one we are trying to delete. deleting this node
409 * from the right subtree is guaranteed to end in one of the
410 * simple cases above.
413 minnode = (*root)->avl_right;
414 while ( minnode->avl_left != NULLAVL )
415 minnode = minnode->avl_left;
418 (*root)->avl_data = minnode->avl_data;
419 minnode->avl_data = savedata;
421 savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
424 if ( shortersubtree )
425 *shorter = right_balance( root );
429 } else if ( cmp < 0 ) {
430 if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
431 &shortersubtree )) == 0 ) {
436 /* left subtree shorter? */
437 if ( shortersubtree )
438 *shorter = left_balance( root );
443 if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
444 &shortersubtree )) == 0 ) {
449 if ( shortersubtree )
450 *shorter = right_balance( root );
459 * avl_delete() - deletes the node containing data (according to fcmp) from
460 * the avl tree rooted at root.
464 avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
468 return( ravl_delete( root, data, fcmp, &shorter ) );
472 avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
475 return( AVL_NOMORE );
477 if ( root->avl_left != 0 )
478 if ( avl_inapply( root->avl_left, fn, arg, stopflag )
482 if ( (*fn)( root->avl_data, arg ) == stopflag )
485 if ( root->avl_right == 0 )
486 return( AVL_NOMORE );
488 return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
492 avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
495 return( AVL_NOMORE );
497 if ( root->avl_left != 0 )
498 if ( avl_postapply( root->avl_left, fn, arg, stopflag )
502 if ( root->avl_right != 0 )
503 if ( avl_postapply( root->avl_right, fn, arg, stopflag )
507 return( (*fn)( root->avl_data, arg ) );
511 avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
514 return( AVL_NOMORE );
516 if ( (*fn)( root->avl_data, arg ) == stopflag )
519 if ( root->avl_left != 0 )
520 if ( avl_preapply( root->avl_left, fn, arg, stopflag )
524 if ( root->avl_right == 0 )
525 return( AVL_NOMORE );
527 return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
531 * avl_apply -- avl tree root is traversed, function fn is called with
532 * arguments arg and the data portion of each node. if fn returns stopflag,
533 * the traversal is cut short, otherwise it continues. Do not use -6 as
534 * a stopflag, as this is what is used to indicate the traversal ran out
539 avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
543 return( avl_inapply( root, fn, arg, stopflag ) );
545 return( avl_preapply( root, fn, arg, stopflag ) );
547 return( avl_postapply( root, fn, arg, stopflag ) );
549 fprintf( stderr, "Invalid traversal type %d\n", type );
557 * avl_prefixapply - traverse avl tree root, applying function fprefix
558 * to any nodes that match. fcmp is called with data as its first arg
559 * and the current node's data as its second arg. it should return
560 * 0 if they match, < 0 if data is less, and > 0 if data is greater.
561 * the idea is to efficiently find all nodes that are prefixes of
562 * some key... Like avl_apply, this routine also takes a stopflag
563 * and will return prematurely if fmatch returns this value. Otherwise,
564 * AVL_NOMORE is returned.
581 return( AVL_NOMORE );
583 cmp = (*fcmp)( data, root->avl_data /* , carg */);
585 if ( (*fmatch)( root->avl_data, marg ) == stopflag )
588 if ( root->avl_left != 0 )
589 if ( avl_prefixapply( root->avl_left, data, fmatch,
590 marg, fcmp, carg, stopflag ) == stopflag )
593 if ( root->avl_right != 0 )
594 return( avl_prefixapply( root->avl_right, data, fmatch,
595 marg, fcmp, carg, stopflag ) );
597 return( AVL_NOMORE );
599 } else if ( cmp < 0 ) {
600 if ( root->avl_left != 0 )
601 return( avl_prefixapply( root->avl_left, data, fmatch,
602 marg, fcmp, carg, stopflag ) );
604 if ( root->avl_right != 0 )
605 return( avl_prefixapply( root->avl_right, data, fmatch,
606 marg, fcmp, carg, stopflag ) );
609 return( AVL_NOMORE );
613 * avl_free -- traverse avltree root, freeing the memory it is using.
614 * the dfree() is called to free the data portion of each node. The
615 * number of items actually freed is returned.
619 avl_free( Avlnode *root, AVL_FREE 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 );
637 return( nleft + nright + 1 );
641 * avl_find -- search avltree root for a node with data data. the function
642 * cmp is used to compare things. it is called with data as its first arg
643 * and the current node data as its second. it should return 0 if they match,
644 * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
648 avl_find2( Avlnode *root, const void *data, AVL_CMP fcmp )
652 while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
654 root = root->avl_left;
656 root = root->avl_right;
662 avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
664 root = avl_find2( root, data, fcmp );
666 return( root ? root->avl_data : 0 );
670 * avl_find_lin -- search avltree root linearly for a node with data data.
671 * the function cmp is used to compare things. it is called with data as its
672 * first arg and the current node data as its second. it should return 0 if
673 * they match, non-zero otherwise.
677 avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
684 if ( (*fcmp)( data, root->avl_data ) == 0 )
685 return( root->avl_data );
687 if ( root->avl_left != 0 )
688 if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
692 if ( root->avl_right == 0 )
695 return( avl_find_lin( root->avl_right, data, fcmp ) );
698 /* NON-REENTRANT INTERFACE */
700 static void* *avl_list;
701 static int avl_maxlist;
702 static int avl_nextlist;
704 #define AVL_GRABSIZE 100
708 avl_buildlist( void* data, void* arg )
712 if ( avl_list == (void* *) 0 ) {
713 avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*));
714 slots = AVL_GRABSIZE;
716 } else if ( avl_maxlist == slots ) {
717 slots += AVL_GRABSIZE;
718 avl_list = (void* *) ber_memrealloc( (char *) avl_list,
719 (unsigned) slots * sizeof(void*));
722 avl_list[ avl_maxlist++ ] = data;
728 * avl_getfirst() and avl_getnext() are provided as alternate tree
729 * traversal methods, to be used when a single function cannot be
730 * provided to be called with every node in the tree. avl_getfirst()
731 * traverses the tree and builds a linear list of all the nodes,
732 * returning the first node. avl_getnext() returns the next thing
733 * on the list built by avl_getfirst(). This means that avl_getfirst()
734 * can take a while, and that the tree should not be messed with while
735 * being traversed in this way, and that multiple traversals (even of
736 * different trees) cannot be active at once.
740 avl_getfirst( Avlnode *root )
743 ber_memfree( (char *) avl_list);
744 avl_list = (void* *) 0;
752 (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
754 return( avl_list[ avl_nextlist++ ] );
763 if ( avl_nextlist == avl_maxlist ) {
764 ber_memfree( (void*) avl_list);
765 avl_list = (void* *) 0;
769 return( avl_list[ avl_nextlist++ ] );
772 /* end non-reentrant code */
776 avl_dup_error( void* left, void* right )
782 avl_dup_ok( void* left, void* right )