1 /* ========================================================================== **
4 * Copyright (C) 1991-1998 by Christopher R. Hertel
6 * Email: crh@ubiqx.mn.org
7 * -------------------------------------------------------------------------- **
9 * This module provides an implementation of AVL height balanced binary
10 * trees. (Adelson-Velskii, Landis 1962)
12 * This file implements the core of the height-balanced (AVL) tree management
13 * routines. The header file, ubi_AVLtree.h, contains function prototypes
14 * for all "exported" functions.
16 * -------------------------------------------------------------------------- **
18 * This library is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU Library General Public
20 * License as published by the Free Software Foundation; either
21 * version 2 of the License, or (at your option) any later version.
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Library General Public License for more details.
28 * You should have received a copy of the GNU Library General Public
29 * License along with this library; if not, write to the Free
30 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 * -------------------------------------------------------------------------- **
34 * Log: ubi_AVLtree.c,v
35 * Revision 4.1 1998/05/20 04:35:50 crh
36 * The C file now includes ubi_null.h. See ubi_null.h for more info.
38 * Revision 4.0 1998/03/10 03:37:09 crh
40 * By adding the AVL balance field to the base ubi_btNode structure, I no
41 * longer need AVL-specific ReplaceNode(), SwapNodes(), and InitNode()
42 * functions. The Remove() function is also simplified. It's all much
44 * This is rev. 4.0. The 3.x series was dropped.
46 * Revision 2.5 1997/12/23 04:00:42 crh
47 * In this version, all constants & macros defined in the header file have
48 * the ubi_tr prefix. Also cleaned up anything that gcc complained about
49 * when run with '-pedantic -fsyntax-only -Wall'.
51 * Revision 2.4 1997/07/26 04:36:20 crh
52 * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied
53 * on backwards with respect to node deletion. I did some more digging and
54 * discovered that I was not changing the balance values correctly in the
55 * single rotation functions. Double rotation was working correctly because
56 * the formula for changing the balance values is the same for insertion or
57 * deletion. Not so for single rotation.
59 * I have tested the fix by loading the tree with over 44 thousand names,
60 * deleting 2,629 of them (all those in which the second character is 'u')
61 * and then walking the tree recursively to verify that the balance factor of
62 * each node is correct. Passed.
67 * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE.
68 * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd
69 * hoped they would do (see the bottom of the header file). They work now.
71 * Revision 2.3 1997/06/03 04:41:35 crh
72 * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing
75 * Revision 2.2 1995/10/03 22:16:01 CRH
78 * Revision 2.1 95/03/09 23:45:59 CRH
79 * Added the ModuleID static string and function. These modules are now
82 * Revision 2.0 95/03/05 14:10:51 CRH
83 * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree,
84 * and so includes all of the changes to that module. In addition, a bug in
85 * the node deletion process has been fixed.
87 * After rewriting the Locate() function in ubi_BinTree, I decided that it was
88 * time to overhaul this module. In the process, I discovered a bug related
89 * to node deletion. To fix the bug, I wrote function Debalance(). A quick
90 * glance will show that it is very similar to the Rebalance() function. In
91 * previous versions of this module, I tried to include the functionality of
92 * Debalance() within Rebalance(), with poor results.
94 * Revision 1.0 93/10/15 22:58:56 CRH
95 * With this revision, I have added a set of #define's that provide a single,
96 * standard API to all existing tree modules. Until now, each of the three
97 * existing modules had a different function and typedef prefix, as follows:
101 * ubi_AVLtree ubi_avl
102 * ubi_SplayTree ubi_spt
104 * To further complicate matters, only those portions of the base module
105 * (ubi_BinTree) that were superceeded in the new module had the new names.
106 * For example, if you were using ubi_SplayTree, the locate function was
107 * called "ubi_sptLocate", but the next and previous functions remained
108 * "ubi_btNext" and "ubi_btPrev".
110 * This was not too terrible if you were familiar with the modules and knew
111 * exactly which tree model you wanted to use. If you wanted to be able to
112 * change modules (for speed comparisons, etc), things could get messy very
115 * So, I have added a set of defined names that get redefined in any of the
116 * descendant modules. To use this standardized interface in your code,
117 * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with
118 * "ubi_tr". The "ubi_tr" names will resolve to the correct function or
119 * datatype names for the module that you are using. Just remember to
120 * include the header for that module in your program file. Because these
121 * names are handled by the preprocessor, there is no added run-time
124 * Note that the original names do still exist, and can be used if you wish
125 * to write code directly to a specific module. This should probably only be
126 * done if you are planning to implement a new descendant type, such as
127 * red/black trees. CRH
129 * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH).
131 * ========================================================================= **
134 #include "ubi_null.h" /* ubiqx NULL source. */
135 #include "ubi_AVLtree.h" /* Header for THIS module. */
137 /* ========================================================================== **
141 static char ModuleID[] = "ubi_AVLtree\n\
143 \tDate: 1998/05/20 04:35:50 \n\
146 /* ========================================================================== **
147 * The next set of functions are the AVL balancing routines. There are left
148 * and right, single and double rotations. The rotation routines handle the
149 * rotations and reconnect all tree pointers that might get confused by the
150 * rotations. A pointer to the new subtree root node is returned.
152 * Note that L1 and R1 are identical, except that all the RIGHTs and LEFTs
153 * are reversed. The same is true for L2 and R2. I'm sure that there is
154 * a clever way to reduce the amount of code by combining these functions,
155 * but it might involve additional overhead, and it would probably be a pain
156 * to read, debug, etc.
157 * -------------------------------------------------------------------------- **
160 static ubi_btNodePtr L1( ubi_btNodePtr p )
161 /* ------------------------------------------------------------------------ **
162 * Single rotate left.
164 * Input: p - Pointer to the root of a tree (possibly a subtree).
165 * Output: A pointer to the new root of the same subtree (now that node
167 * ------------------------------------------------------------------------ **
172 tmp = p->Link[ubi_trRIGHT];
173 p->Link[ubi_trRIGHT] = tmp->Link[ubi_trLEFT];
174 tmp->Link[ubi_trLEFT] = p;
176 tmp->Link[ubi_trPARENT] = p->Link[ubi_trPARENT];
177 tmp->gender = p->gender;
178 if(tmp->Link[ubi_trPARENT])
179 (tmp->Link[ubi_trPARENT])->Link[(int)(tmp->gender)] = tmp;
180 p->Link[ubi_trPARENT] = tmp;
181 p->gender = ubi_trLEFT;
182 if( p->Link[ubi_trRIGHT] )
184 p->Link[ubi_trRIGHT]->Link[ubi_trPARENT] = p;
185 (p->Link[ubi_trRIGHT])->gender = ubi_trRIGHT;
187 p->balance -= ubi_trNormalize( tmp->balance );
192 static ubi_btNodePtr R1( ubi_btNodePtr p )
193 /* ------------------------------------------------------------------------ **
194 * Single rotate right.
196 * Input: p - Pointer to the root of a tree (possibly a subtree).
197 * Output: A pointer to the new root of the same subtree (now that node
199 * ------------------------------------------------------------------------ **
204 tmp = p->Link[ubi_trLEFT];
205 p->Link[ubi_trLEFT] = tmp->Link[ubi_trRIGHT];
206 tmp->Link[ubi_trRIGHT] = p;
208 tmp->Link[ubi_trPARENT] = p->Link[ubi_trPARENT];
209 tmp->gender = p->gender;
210 if(tmp->Link[ubi_trPARENT])
211 (tmp->Link[ubi_trPARENT])->Link[(int)(tmp->gender)] = tmp;
212 p->Link[ubi_trPARENT] = tmp;
213 p->gender = ubi_trRIGHT;
214 if(p->Link[ubi_trLEFT])
216 p->Link[ubi_trLEFT]->Link[ubi_trPARENT] = p;
217 p->Link[ubi_trLEFT]->gender = ubi_trLEFT;
219 p->balance -= ubi_trNormalize( tmp->balance );
224 static ubi_btNodePtr L2( ubi_btNodePtr tree )
225 /* ------------------------------------------------------------------------ **
226 * Double rotate left.
228 * Input: p - Pointer to the root of a tree (possibly a subtree).
229 * Output: A pointer to the new root of the same subtree (now that node
231 * ------------------------------------------------------------------------ **
234 ubi_btNodePtr tmp, newroot;
236 tmp = tree->Link[ubi_trRIGHT];
237 newroot = tmp->Link[ubi_trLEFT];
238 tmp->Link[ubi_trLEFT] = newroot->Link[ubi_trRIGHT];
239 newroot->Link[ubi_trRIGHT] = tmp;
240 tree->Link[ubi_trRIGHT] = newroot->Link[ubi_trLEFT];
241 newroot->Link[ubi_trLEFT] = tree;
243 newroot->Link[ubi_trPARENT] = tree->Link[ubi_trPARENT];
244 newroot->gender = tree->gender;
245 tree->Link[ubi_trPARENT] = newroot;
246 tree->gender = ubi_trLEFT;
247 tmp->Link[ubi_trPARENT] = newroot;
248 tmp->gender = ubi_trRIGHT;
250 if( tree->Link[ubi_trRIGHT] )
252 tree->Link[ubi_trRIGHT]->Link[ubi_trPARENT] = tree;
253 tree->Link[ubi_trRIGHT]->gender = ubi_trRIGHT;
255 if( tmp->Link[ubi_trLEFT] )
257 tmp->Link[ubi_trLEFT]->Link[ubi_trPARENT] = tmp;
258 tmp->Link[ubi_trLEFT]->gender = ubi_trLEFT;
260 if(newroot->Link[ubi_trPARENT])
261 newroot->Link[ubi_trPARENT]->Link[(int)(newroot->gender)] = newroot;
263 switch( newroot->balance )
266 tree->balance = ubi_trEQUAL; tmp->balance = ubi_trRIGHT; break;
268 tree->balance = ubi_trEQUAL; tmp->balance = ubi_trEQUAL; break;
270 tree->balance = ubi_trLEFT; tmp->balance = ubi_trEQUAL; break;
272 newroot->balance = ubi_trEQUAL;
276 static ubi_btNodePtr R2( ubi_btNodePtr tree )
277 /* ------------------------------------------------------------------------ **
278 * Double rotate right.
280 * Input: p - Pointer to the root of a tree (possibly a subtree).
281 * Output: A pointer to the new root of the same subtree (now that node
283 * ------------------------------------------------------------------------ **
286 ubi_btNodePtr tmp, newroot;
288 tmp = tree->Link[ubi_trLEFT];
289 newroot = tmp->Link[ubi_trRIGHT];
290 tmp->Link[ubi_trRIGHT] = newroot->Link[ubi_trLEFT];
291 newroot->Link[ubi_trLEFT] = tmp;
292 tree->Link[ubi_trLEFT] = newroot->Link[ubi_trRIGHT];
293 newroot->Link[ubi_trRIGHT] = tree;
295 newroot->Link[ubi_trPARENT] = tree->Link[ubi_trPARENT];
296 newroot->gender = tree->gender;
297 tree->Link[ubi_trPARENT] = newroot;
298 tree->gender = ubi_trRIGHT;
299 tmp->Link[ubi_trPARENT] = newroot;
300 tmp->gender = ubi_trLEFT;
302 if( tree->Link[ubi_trLEFT] )
304 tree->Link[ubi_trLEFT]->Link[ubi_trPARENT] = tree;
305 tree->Link[ubi_trLEFT]->gender = ubi_trLEFT;
307 if( tmp->Link[ubi_trRIGHT] )
309 tmp->Link[ubi_trRIGHT]->Link[ubi_trPARENT] = tmp;
310 tmp->Link[ubi_trRIGHT]->gender = ubi_trRIGHT;
312 if(newroot->Link[ubi_trPARENT])
313 newroot->Link[ubi_trPARENT]->Link[(int)(newroot->gender)] = newroot;
315 switch( newroot->balance )
318 tree->balance = ubi_trRIGHT; tmp->balance = ubi_trEQUAL; break;
320 tree->balance = ubi_trEQUAL; tmp->balance = ubi_trEQUAL; break;
322 tree->balance = ubi_trEQUAL; tmp->balance = ubi_trLEFT; break;
324 newroot->balance = ubi_trEQUAL;
329 static ubi_btNodePtr Adjust( ubi_btNodePtr p, char LorR )
330 /* ------------------------------------------------------------------------ **
331 * Adjust the balance value at node *p. If necessary, rotate the subtree
334 * Input: p - A pointer to the node to be adjusted. One of the
335 * subtrees of this node has changed height, so the
336 * balance value at this node must be adjusted, possibly
337 * by rotating the tree at this node.
338 * LorR - Indicates the TALLER subtree.
340 * Output: A pointer to the (possibly new) root node of the subtree.
342 * Notes: This function may be called after a node has been added *or*
343 * deleted, so LorR indicates the TALLER subtree.
344 * ------------------------------------------------------------------------ **
347 if( p->balance != LorR )
348 p->balance += ubi_trNormalize(LorR);
351 char tallerbal; /* Balance value of the root of the taller subtree of p. */
353 tallerbal = p->Link[(int)LorR]->balance;
354 if( ( ubi_trEQUAL == tallerbal ) || ( p->balance == tallerbal ) )
355 p = ( (ubi_trLEFT==LorR) ? R1(p) : L1(p) ); /* single rotation */
357 p = ( (ubi_trLEFT==LorR) ? R2(p) : L2(p) ); /* double rotation */
362 static ubi_btNodePtr Rebalance( ubi_btNodePtr Root,
363 ubi_btNodePtr subtree,
365 /* ------------------------------------------------------------------------ **
366 * Rebalance the tree following an insertion.
368 * Input: Root - A pointer to the root node of the whole tree.
369 * subtree - A pointer to the node that has just gained a new
371 * LorR - Gender of the child that has just been gained.
373 * Output: A pointer to the (possibly new) root of the AVL tree.
374 * Rebalancing the tree moves nodes around a bit, so the node
375 * that *was* the root, may not be the root when we're finished.
377 * Notes: Rebalance() must walk up the tree from where we are (which is
378 * where the latest change occurred), rebalancing the subtrees
379 * along the way. The rebalancing operation can stop if the
380 * change at the current subtree root won't affect the rest of
381 * the tree. In the case of an addition, if a subtree root's
382 * balance becomes EQUAL, then we know that the height of that
383 * subtree has not changed, so we can exit.
384 * ------------------------------------------------------------------------ **
389 subtree = Adjust( subtree, LorR );
390 if( ubi_trPARENT == subtree->gender )
392 if( ubi_trEQUAL == subtree->balance )
394 LorR = subtree->gender;
395 subtree = subtree->Link[ubi_trPARENT];
400 static ubi_btNodePtr Debalance( ubi_btNodePtr Root,
401 ubi_btNodePtr subtree,
403 /* ------------------------------------------------------------------------ **
404 * Rebalance the tree following a deletion.
406 * Input: Root - A pointer to the root node of the whole tree.
407 * subtree - A pointer to the node who's child has just "left the
409 * LorR - Gender of the child that left.
411 * Output: A pointer to the (possibly new) root of the AVL tree.
412 * Rebalancing the tree moves nodes around a bit, so the node
413 * that *was* the root, may not be the root when we're finished.
415 * Notes: Debalance() is subtly different from Rebalance() (above) in
417 * * When it calls Adjust(), it passes the *opposite* of LorR.
418 * This is because LorR, as passed into Debalance() indicates
419 * the shorter subtree. As we move up the tree, LorR is
420 * assigned the gender of the node that we are leaving (i.e.,
421 * the subtree that we just rebalanced).
422 * * We know that a subtree has not changed height if the
423 * balance becomes LEFT or RIGHT. This is the *opposite* of
424 * what happens in Rebalance().
425 * ------------------------------------------------------------------------ **
430 subtree = Adjust( subtree, ubi_trRevWay(LorR) );
431 if( ubi_trPARENT == subtree->gender )
433 if( ubi_trEQUAL != subtree->balance )
435 LorR = subtree->gender;
436 subtree = subtree->Link[ubi_trPARENT];
441 /* ========================================================================== **
442 * Public, exported (ie. not static-ly declared) functions...
443 * -------------------------------------------------------------------------- **
446 ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
447 ubi_btNodePtr NewNode,
448 ubi_btItemPtr ItemPtr,
449 ubi_btNodePtr *OldNode )
450 /* ------------------------------------------------------------------------ **
451 * This function uses a non-recursive algorithm to add a new element to
454 * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
455 * the root of the tree to which NewNode is to be added.
456 * NewNode - a pointer to an ubi_btNode structure that is NOT
458 * ItemPtr - A pointer to the sort key that is stored within
459 * *NewNode. ItemPtr MUST point to information stored
460 * in *NewNode or an EXACT DUPLICATE. The key data
461 * indicated by ItemPtr is used to place the new node
463 * OldNode - a pointer to an ubi_btNodePtr. When searching
464 * the tree, a duplicate node may be found. If
465 * duplicates are allowed, then the new node will
466 * be simply placed into the tree. If duplicates
467 * are not allowed, however, then one of two things
469 * 1) if overwritting *is not* allowed, this
470 * function will return FALSE (indicating that
471 * the new node could not be inserted), and
472 * *OldNode will point to the duplicate that is
474 * 2) if overwritting *is* allowed, then this
475 * function will swap **OldNode for *NewNode.
476 * In this case, *OldNode will point to the node
477 * that was removed (thus allowing you to free
479 * ** If you are using overwrite mode, ALWAYS **
480 * ** check the return value of this parameter! **
481 * Note: You may pass NULL in this parameter, the
482 * function knows how to cope. If you do this,
483 * however, there will be no way to return a
484 * pointer to an old (ie. replaced) node (which is
485 * a problem if you are using overwrite mode).
487 * Output: a boolean value indicating success or failure. The function
488 * will return FALSE if the node could not be added to the tree.
489 * Such failure will only occur if duplicates are not allowed,
490 * nodes cannot be overwritten, AND a duplicate key was found
492 * ------------------------------------------------------------------------ **
495 ubi_btNodePtr OtherP;
499 if( ubi_btInsert( RootPtr,
500 (ubi_btNodePtr)NewNode,
502 (ubi_btNodePtr *)OldNode ) )
505 NewNode->balance = (*OldNode)->balance;
508 NewNode->balance = ubi_trEQUAL;
509 RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_btNodePtr)RootPtr->root,
510 NewNode->Link[ubi_trPARENT],
513 return( ubi_trTRUE );
515 return( ubi_trFALSE ); /* Failure: could not replace an existing node. */
516 } /* ubi_avlInsert */
518 ubi_btNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr,
519 ubi_btNodePtr DeadNode )
520 /* ------------------------------------------------------------------------ **
521 * This function removes the indicated node from the tree, after which the
522 * tree is rebalanced.
524 * Input: RootPtr - A pointer to the header of the tree that contains
525 * the node to be removed.
526 * DeadNode - A pointer to the node that will be removed.
528 * Output: This function returns a pointer to the node that was removed
529 * from the tree (ie. the same as DeadNode).
531 * Note: The node MUST be in the tree indicated by RootPtr. If not,
532 * strange and evil things will happen to your trees.
534 * ------------------------------------------------------------------------ **
537 /* Let the base binary tree module do the removal, then rebalance. */
538 if( ubi_btRemove( RootPtr, DeadNode ) )
539 RootPtr->root = Debalance( RootPtr->root,
540 DeadNode->Link[ubi_trPARENT],
543 } /* ubi_avlRemove */
545 int ubi_avlModuleID( int size, char *list[] )
546 /* ------------------------------------------------------------------------ **
547 * Returns a set of strings that identify the module.
549 * Input: size - The number of elements in the array <list>.
550 * list - An array of pointers of type (char *). This array
551 * should, initially, be empty. This function will fill
552 * in the array with pointers to strings.
553 * Output: The number of elements of <list> that were used. If this value
554 * is less than <size>, the values of the remaining elements are
557 * Notes: Please keep in mind that the pointers returned indicate strings
558 * stored in static memory. Don't free() them, don't write over
559 * them, etc. Just read them.
560 * ------------------------------------------------------------------------ **
567 return( 1 + ubi_btModuleID( --size, &(list[1]) ) );
571 } /* ubi_avlModuleID */
573 /* ============================== The End ============================== */