]> git.sur5r.net Git - openldap/blob - libraries/libavl/avl.c
be18d60c74131d1d638d684ea242d6669f293f96
[openldap] / libraries / libavl / avl.c
1 /* avl.c - routines to implement an avl tree */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7 /*
8  * Copyright (c) 1993 Regents of the University of Michigan.
9  * All rights reserved.
10  *
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.
17  */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22 #include <ac/stdlib.h>
23
24 #ifdef CSRIMALLOC
25 #define ber_memalloc malloc
26 #define ber_memrealloc realloc
27 #define ber_memfree free
28 #else
29 #include "lber.h"
30 #endif
31
32 #define AVL_INTERNAL
33 #include "avl.h"
34
35 #define ROTATERIGHT(x)  { \
36         Avlnode *tmp;\
37         if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
38                 (void) fputs("RR error\n", stderr); exit( EXIT_FAILURE ); \
39         }\
40         tmp = (*(x))->avl_left;\
41         (*(x))->avl_left = tmp->avl_right;\
42         tmp->avl_right = *(x);\
43         *(x) = tmp;\
44 }
45 #define ROTATELEFT(x)   { \
46         Avlnode *tmp;\
47         if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
48                 (void) fputs("RL error\n", stderr); exit( EXIT_FAILURE ); \
49         }\
50         tmp = (*(x))->avl_right;\
51         (*(x))->avl_right = tmp->avl_left;\
52         tmp->avl_left = *(x);\
53         *(x) = tmp;\
54 }
55
56 /*
57  * ravl_insert - called from avl_insert() to do a recursive insert into
58  * and balance of an avl tree.
59  */
60
61 static int
62 ravl_insert(
63     Avlnode     **iroot,
64     void*       data,
65     int         *taller,
66     AVL_CMP             fcmp,                   /* comparison function */
67     AVL_DUP             fdup,                   /* function to call for duplicates */
68     int         depth
69 )
70 {
71         int     rc, cmp, tallersub;
72         Avlnode *l, *r;
73
74         if ( *iroot == 0 ) {
75                 if ( (*iroot = (Avlnode *) ber_memalloc( sizeof( Avlnode ) ))
76                     == NULL ) {
77                         return( -1 );
78                 }
79                 (*iroot)->avl_left = 0;
80                 (*iroot)->avl_right = 0;
81                 (*iroot)->avl_bf = 0;
82                 (*iroot)->avl_data = data;
83                 *taller = 1;
84                 return( 0 );
85         }
86
87         cmp = (*fcmp)( data, (*iroot)->avl_data );
88
89         /* equal - duplicate name */
90         if ( cmp == 0 ) {
91                 *taller = 0;
92                 return( (*fdup)( (*iroot)->avl_data, data ) );
93         }
94
95         /* go right */
96         else if ( cmp > 0 ) {
97                 rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
98                    fcmp, fdup, depth );
99                 if ( tallersub )
100                         switch ( (*iroot)->avl_bf ) {
101                         case LH : /* left high - balance is restored */
102                                 (*iroot)->avl_bf = EH;
103                                 *taller = 0;
104                                 break;
105                         case EH : /* equal height - now right heavy */
106                                 (*iroot)->avl_bf = RH;
107                                 *taller = 1;
108                                 break;
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 */
113                                         l = r->avl_left;
114                                         switch ( l->avl_bf ) {
115                                         case LH : (*iroot)->avl_bf = EH;
116                                                   r->avl_bf = RH;
117                                                   break;
118                                         case EH : (*iroot)->avl_bf = EH;
119                                                   r->avl_bf = EH;
120                                                   break;
121                                         case RH : (*iroot)->avl_bf = LH;
122                                                   r->avl_bf = EH;
123                                                   break;
124                                         }
125                                         l->avl_bf = EH;
126                                         ROTATERIGHT( (&r) )
127                                         (*iroot)->avl_right = r;
128                                         ROTATELEFT( iroot )
129                                         *taller = 0;
130                                         break;
131                                 case EH : /* This should never happen */
132                                         break;
133                                 case RH : /* single rotation left */
134                                         (*iroot)->avl_bf = EH;
135                                         r->avl_bf = EH;
136                                         ROTATELEFT( iroot )
137                                         *taller = 0;
138                                         break;
139                                 }
140                                 break;
141                         }
142                 else
143                         *taller = 0;
144         }
145
146         /* go left */
147         else {
148                 rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
149                    fcmp, fdup, depth );
150                 if ( 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;
157                                         l->avl_bf = EH;
158                                         ROTATERIGHT( iroot )
159                                         *taller = 0;
160                                         break;
161                                 case EH : /* this should never happen */
162                                         break;
163                                 case RH : /* double rotation right */
164                                         r = l->avl_right;
165                                         switch ( r->avl_bf ) {
166                                         case LH : (*iroot)->avl_bf = RH;
167                                                   l->avl_bf = EH;
168                                                   break;
169                                         case EH : (*iroot)->avl_bf = EH;
170                                                   l->avl_bf = EH;
171                                                   break;
172                                         case RH : (*iroot)->avl_bf = EH;
173                                                   l->avl_bf = LH;
174                                                   break;
175                                         }
176                                         r->avl_bf = EH;
177                                         ROTATELEFT( (&l) )
178                                         (*iroot)->avl_left = l;
179                                         ROTATERIGHT( iroot )
180                                         *taller = 0;
181                                         break;
182                                 }
183                                 break;
184                         case EH : /* equal height - now left heavy */
185                                 (*iroot)->avl_bf = LH;
186                                 *taller = 1;
187                                 break;
188                         case RH : /* right high - balance is restored */
189                                 (*iroot)->avl_bf = EH;
190                                 *taller = 0;
191                                 break;
192                         }
193                 else
194                         *taller = 0;
195         }
196
197         return( rc );
198 }
199
200 /*
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
211  * node.
212  *
213  * NOTE: this routine may malloc memory
214  */
215
216 int
217 avl_insert( Avlnode **root, void* data, AVL_CMP fcmp, AVL_DUP fdup )
218 {
219         int     taller;
220
221         return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
222 }
223
224 /* 
225  * right_balance() - called from delete when root's right subtree has
226  * been shortened because of a deletion.
227  */
228
229 static int
230 right_balance( Avlnode **root )
231 {
232         int     shorter = -1;
233         Avlnode *r, *l;
234
235         switch( (*root)->avl_bf ) {
236         case RH:        /* was right high - equal now */
237                 (*root)->avl_bf = EH;
238                 shorter = 1;
239                 break;
240         case EH:        /* was equal - left high now */
241                 (*root)->avl_bf = LH;
242                 shorter = 0;
243                 break;
244         case LH:        /* was right high - balance */
245                 l = (*root)->avl_left;
246                 switch ( l->avl_bf ) {
247                 case RH : /* double rotation left */
248                         r = l->avl_right;
249                         switch ( r->avl_bf ) {
250                         case RH :
251                                 (*root)->avl_bf = EH;
252                                 l->avl_bf = LH;
253                                 break;
254                         case EH :
255                                 (*root)->avl_bf = EH;
256                                 l->avl_bf = EH;
257                                 break;
258                         case LH :
259                                 (*root)->avl_bf = RH;
260                                 l->avl_bf = EH;
261                                 break;
262                         }
263                         r->avl_bf = EH;
264                         ROTATELEFT( (&l) )
265                         (*root)->avl_left = l;
266                         ROTATERIGHT( root )
267                         shorter = 1;
268                         break;
269                 case EH : /* right rotation */
270                         (*root)->avl_bf = LH;
271                         l->avl_bf = RH;
272                         ROTATERIGHT( root );
273                         shorter = 0;
274                         break;
275                 case LH : /* single rotation right */
276                         (*root)->avl_bf = EH;
277                         l->avl_bf = EH;
278                         ROTATERIGHT( root )
279                         shorter = 1;
280                         break;
281                 }
282                 break;
283         }
284
285         return( shorter );
286 }
287
288 /* 
289  * left_balance() - called from delete when root's left subtree has
290  * been shortened because of a deletion.
291  */
292
293 static int
294 left_balance( Avlnode **root )
295 {
296         int     shorter = -1;
297         Avlnode *r, *l;
298
299         switch( (*root)->avl_bf ) {
300         case LH:        /* was left high - equal now */
301                 (*root)->avl_bf = EH;
302                 shorter = 1;
303                 break;
304         case EH:        /* was equal - right high now */
305                 (*root)->avl_bf = RH;
306                 shorter = 0;
307                 break;
308         case RH:        /* was right high - balance */
309                 r = (*root)->avl_right;
310                 switch ( r->avl_bf ) {
311                 case LH : /* double rotation left */
312                         l = r->avl_left;
313                         switch ( l->avl_bf ) {
314                         case LH :
315                                 (*root)->avl_bf = EH;
316                                 r->avl_bf = RH;
317                                 break;
318                         case EH :
319                                 (*root)->avl_bf = EH;
320                                 r->avl_bf = EH;
321                                 break;
322                         case RH :
323                                 (*root)->avl_bf = LH;
324                                 r->avl_bf = EH;
325                                 break;
326                         }
327                         l->avl_bf = EH;
328                         ROTATERIGHT( (&r) )
329                         (*root)->avl_right = r;
330                         ROTATELEFT( root )
331                         shorter = 1;
332                         break;
333                 case EH : /* single rotation left */
334                         (*root)->avl_bf = RH;
335                         r->avl_bf = LH;
336                         ROTATELEFT( root );
337                         shorter = 0;
338                         break;
339                 case RH : /* single rotation left */
340                         (*root)->avl_bf = EH;
341                         r->avl_bf = EH;
342                         ROTATELEFT( root )
343                         shorter = 1;
344                         break;
345                 }
346                 break;
347         }
348
349         return( shorter );
350 }
351
352 /*
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
356  * rebalancing.
357  */
358
359 static void*
360 ravl_delete( Avlnode **root, void* data, AVL_CMP fcmp, int *shorter )
361 {
362         int     shortersubtree = 0;
363         int     cmp;
364         void*   savedata;
365         Avlnode *minnode, *savenode;
366
367         if ( *root == NULLAVL )
368                 return( 0 );
369
370         cmp = (*fcmp)( data, (*root)->avl_data );
371
372         /* found it! */
373         if ( cmp == 0 ) {
374                 savenode = *root;
375                 savedata = savenode->avl_data;
376
377                 /* simple cases: no left child */
378                 if ( (*root)->avl_left == 0 ) {
379                         *root = (*root)->avl_right;
380                         *shorter = 1;
381                         ber_memfree( (char *) savenode );
382                         return( savedata );
383                 /* no right child */
384                 } else if ( (*root)->avl_right == 0 ) {
385                         *root = (*root)->avl_left;
386                         *shorter = 1;
387                         ber_memfree( (char *) savenode );
388                         return( savedata );
389                 }
390
391                 /* 
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.
396                  */
397
398                 minnode = (*root)->avl_right;
399                 while ( minnode->avl_left != NULLAVL )
400                         minnode = minnode->avl_left;
401
402                 /* swap the data */
403                 (*root)->avl_data = minnode->avl_data;
404                 minnode->avl_data = savedata;
405
406                 savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
407                     &shortersubtree );
408
409                 if ( shortersubtree )
410                         *shorter = right_balance( root );
411                 else
412                         *shorter = 0;
413         /* go left */
414         } else if ( cmp < 0 ) {
415                 if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
416                     &shortersubtree )) == 0 ) {
417                         *shorter = 0;
418                         return( 0 );
419                 }
420
421                 /* left subtree shorter? */
422                 if ( shortersubtree )
423                         *shorter = left_balance( root );
424                 else
425                         *shorter = 0;
426         /* go right */
427         } else {
428                 if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
429                     &shortersubtree )) == 0 ) {
430                         *shorter = 0;
431                         return( 0 );
432                 }
433
434                 if ( shortersubtree ) 
435                         *shorter = right_balance( root );
436                 else
437                         *shorter = 0;
438         }
439
440         return( savedata );
441 }
442
443 /*
444  * avl_delete() - deletes the node containing data (according to fcmp) from
445  * the avl tree rooted at root.
446  */
447
448 void*
449 avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
450 {
451         int     shorter;
452
453         return( ravl_delete( root, data, fcmp, &shorter ) );
454 }
455
456 static int
457 avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
458 {
459         if ( root == 0 )
460                 return( AVL_NOMORE );
461
462         if ( root->avl_left != 0 )
463                 if ( avl_inapply( root->avl_left, fn, arg, stopflag ) 
464                     == stopflag )
465                         return( stopflag );
466
467         if ( (*fn)( root->avl_data, arg ) == stopflag )
468                 return( stopflag );
469
470         if ( root->avl_right == 0 )
471                 return( AVL_NOMORE );
472         else
473                 return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
474 }
475
476 static int
477 avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
478 {
479         if ( root == 0 )
480                 return( AVL_NOMORE );
481
482         if ( root->avl_left != 0 )
483                 if ( avl_postapply( root->avl_left, fn, arg, stopflag ) 
484                     == stopflag )
485                         return( stopflag );
486
487         if ( root->avl_right != 0 )
488                 if ( avl_postapply( root->avl_right, fn, arg, stopflag ) 
489                     == stopflag )
490                         return( stopflag );
491
492         return( (*fn)( root->avl_data, arg ) );
493 }
494
495 static int
496 avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
497 {
498         if ( root == 0 )
499                 return( AVL_NOMORE );
500
501         if ( (*fn)( root->avl_data, arg ) == stopflag )
502                 return( stopflag );
503
504         if ( root->avl_left != 0 )
505                 if ( avl_preapply( root->avl_left, fn, arg, stopflag ) 
506                     == stopflag )
507                         return( stopflag );
508
509         if ( root->avl_right == 0 )
510                 return( AVL_NOMORE );
511         else
512                 return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
513 }
514
515 /*
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
520  * of nodes.
521  */
522
523 int
524 avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
525 {
526         switch ( type ) {
527         case AVL_INORDER:
528                 return( avl_inapply( root, fn, arg, stopflag ) );
529         case AVL_PREORDER:
530                 return( avl_preapply( root, fn, arg, stopflag ) );
531         case AVL_POSTORDER:
532                 return( avl_postapply( root, fn, arg, stopflag ) );
533         default:
534                 fprintf( stderr, "Invalid traversal type %d\n", type );
535                 return( -1 );
536         }
537
538         /* NOTREACHED */
539 }
540
541 /*
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.
550  */
551
552 int
553 avl_prefixapply(
554     Avlnode     *root,
555     void*       data,
556     AVL_CMP             fmatch,
557     void*       marg,
558     AVL_CMP             fcmp,
559     void*       carg,
560     int         stopflag
561 )
562 {
563         int     cmp;
564
565         if ( root == 0 )
566                 return( AVL_NOMORE );
567
568         cmp = (*fcmp)( data, root->avl_data /* , carg */);
569         if ( cmp == 0 ) {
570                 if ( (*fmatch)( root->avl_data, marg ) == stopflag )
571                         return( stopflag );
572
573                 if ( root->avl_left != 0 )
574                         if ( avl_prefixapply( root->avl_left, data, fmatch,
575                             marg, fcmp, carg, stopflag ) == stopflag )
576                                 return( stopflag );
577
578                 if ( root->avl_right != 0 )
579                         return( avl_prefixapply( root->avl_right, data, fmatch,
580                             marg, fcmp, carg, stopflag ) );
581                 else
582                         return( AVL_NOMORE );
583
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 ) );
588         } else {
589                 if ( root->avl_right != 0 )
590                         return( avl_prefixapply( root->avl_right, data, fmatch,
591                             marg, fcmp, carg, stopflag ) );
592         }
593
594         return( AVL_NOMORE );
595 }
596
597 /*
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.
601  */
602
603 int
604 avl_free( Avlnode *root, AVL_FREE dfree )
605 {
606         int     nleft, nright;
607
608         if ( root == 0 )
609                 return( 0 );
610
611         nleft = nright = 0;
612         if ( root->avl_left != 0 )
613                 nleft = avl_free( root->avl_left, dfree );
614
615         if ( root->avl_right != 0 )
616                 nright = avl_free( root->avl_right, dfree );
617
618         if ( dfree )
619                 (*dfree)( root->avl_data );
620         ber_memfree( root );
621
622         return( nleft + nright + 1 );
623 }
624
625 /*
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.
630  */
631
632 void*
633 avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
634 {
635         int     cmp;
636
637         while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
638                 if ( cmp < 0 )
639                         root = root->avl_left;
640                 else
641                         root = root->avl_right;
642         }
643
644         return( root ? root->avl_data : 0 );
645 }
646
647 /*
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.
652  */
653
654 void*
655 avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
656 {
657         void*   res;
658
659         if ( root == 0 )
660                 return( NULL );
661
662         if ( (*fcmp)( data, root->avl_data ) == 0 )
663                 return( root->avl_data );
664
665         if ( root->avl_left != 0 )
666                 if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
667                     != NULL )
668                         return( res );
669
670         if ( root->avl_right == 0 )
671                 return( NULL );
672         else
673                 return( avl_find_lin( root->avl_right, data, fcmp ) );
674 }
675
676 /* NON-REENTRANT INTERFACE */
677
678 static void*    *avl_list;
679 static int      avl_maxlist;
680 static int      avl_nextlist;
681
682 #define AVL_GRABSIZE    100
683
684 /* ARGSUSED */
685 static int
686 avl_buildlist( void* data, void* arg )
687 {
688         static int      slots;
689
690         if ( avl_list == (void* *) 0 ) {
691                 avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*));
692                 slots = AVL_GRABSIZE;
693                 avl_maxlist = 0;
694         } else if ( avl_maxlist == slots ) {
695                 slots += AVL_GRABSIZE;
696                 avl_list = (void* *) ber_memrealloc( (char *) avl_list,
697                     (unsigned) slots * sizeof(void*));
698         }
699
700         avl_list[ avl_maxlist++ ] = data;
701
702         return( 0 );
703 }
704
705 /*
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.
715  */
716
717 void*
718 avl_getfirst( Avlnode *root )
719 {
720         if ( avl_list ) {
721                 ber_memfree( (char *) avl_list);
722                 avl_list = (void* *) 0;
723         }
724         avl_maxlist = 0;
725         avl_nextlist = 0;
726
727         if ( root == 0 )
728                 return( 0 );
729
730         (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
731
732         return( avl_list[ avl_nextlist++ ] );
733 }
734
735 void*
736 avl_getnext( void )
737 {
738         if ( avl_list == 0 )
739                 return( 0 );
740
741         if ( avl_nextlist == avl_maxlist ) {
742                 ber_memfree( (void*) avl_list);
743                 avl_list = (void* *) 0;
744                 return( 0 );
745         }
746
747         return( avl_list[ avl_nextlist++ ] );
748 }
749
750 /* end non-reentrant code */
751
752
753 int
754 avl_dup_error( void* left, void* right )
755 {
756         return( -1 );
757 }
758
759 int
760 avl_dup_ok( void* left, void* right )
761 {
762         return( 0 );
763 }