ubi_SplayTree.c

00001 /* ========================================================================== **
00002  *                              ubi_SplayTree.c
00003  *
00004  *  Copyright (C) 1993-1998 by Christopher R. Hertel
00005  *
00006  *  Email: crh@ubiqx.mn.org
00007  * -------------------------------------------------------------------------- **
00008  *
00009  *  This module implements "splay" trees.  Splay trees are binary trees
00010  *  that are rearranged (splayed) whenever a node is accessed.  The
00011  *  splaying process *tends* to make the tree bushier (improves balance),
00012  *  and the nodes that are accessed most frequently *tend* to be closer to
00013  *  the top.
00014  *
00015  *  References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and
00016  *              Robert Tarjan.  Journal of the Association for Computing
00017  *              Machinery Vol 32, No. 3, July 1985 pp. 652-686
00018  *
00019  *    See also: http://www.cs.cmu.edu/~sleator/
00020  *
00021  * -------------------------------------------------------------------------- **
00022  *
00023  *  This library is free software; you can redistribute it and/or
00024  *  modify it under the terms of the GNU Library General Public
00025  *  License as published by the Free Software Foundation; either
00026  *  version 2 of the License, or (at your option) any later version.
00027  *
00028  *  This library is distributed in the hope that it will be useful,
00029  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00030  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00031  *  Library General Public License for more details.
00032  *
00033  *  You should have received a copy of the GNU Library General Public
00034  *  License along with this library; if not, write to the Free
00035  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00036  *
00037  * -------------------------------------------------------------------------- **
00038  *
00039  * $Log: ubi_SplayTree.c,v $
00040  * Revision 1.1  2004/01/14 20:27:14  dwarren
00041  * XSB Prolog Profiling as command line option -p
00042  *
00043  * Revision 4.5  2000/01/08 23:26:49  crh
00044  * Added ubi_trSplay() macro, which does a type cast for us.
00045  *
00046  * Revision 4.4  1998/06/04 21:29:27  crh
00047  * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
00048  * This is more "standard", and is what people expect.  Weird, eh?
00049  *
00050  * Revision 4.3  1998/06/03 17:45:05  crh
00051  * Further fiddling with sys_include.h.  It's now in ubi_BinTree.h which is
00052  * included by all of the binary tree files.
00053  *
00054  * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem
00055  * to like syntax like this:
00056  *
00057  *   if( (a = b) )
00058  *
00059  * The fix was to change lines like the above to:
00060  *
00061  *   if( 0 != (a=b) )
00062  *
00063  * Which means the same thing.
00064  *
00065  * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in
00066  *           ubi_AVLtree.h and ubi_SplayTree.h.  This allows easy swapping
00067  *           of tree types by simply changing a header.  Unfortunately, the
00068  *           macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will
00069  *           conflict if used together.  You must either choose a single tree
00070  *           type, or use the underlying function calls directly.  Compare
00071  *           the two header files for more information.
00072  *
00073  * Revision 4.2  1998/06/02 01:29:14  crh
00074  * Changed ubi_null.h to sys_include.h to make it more generic.
00075  *
00076  * Revision 4.1  1998/05/20 04:37:54  crh
00077  * The C file now includes ubi_null.h.  See ubi_null.h for more info.
00078  *
00079  * Revision 4.0  1998/03/10 03:41:33  crh
00080  * Minor comment changes.  The revision number is now 4.0 to match the
00081  * BinTree and AVLtree modules.
00082  *
00083  * Revision 2.7  1998/01/24 06:37:08  crh
00084  * Added a URL for more information.
00085  *
00086  * Revision 2.6  1997/12/23 04:01:12  crh
00087  * In this version, all constants & macros defined in the header file have
00088  * the ubi_tr prefix.  Also cleaned up anything that gcc complained about
00089  * when run with '-pedantic -fsyntax-only -Wall'.
00090  *
00091  * Revision 2.5  1997/07/26 04:15:42  crh
00092  * + Cleaned up a few minor syntax annoyances that gcc discovered for me.
00093  * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE.
00094  *
00095  * Revision 2.4  1997/06/03 04:42:21  crh
00096  * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing
00097  * problems.
00098  *
00099  * Revision 2.3  1995/10/03 22:19:07  CRH
00100  * Ubisized!
00101  * Also, added the function ubi_sptSplay().
00102  *
00103  * Revision 2.1  95/03/09  23:54:42  CRH
00104  * Added the ModuleID static string and function.  These modules are now
00105  * self-identifying.
00106  * 
00107  * Revision 2.0  95/02/27  22:34:46  CRH
00108  * This module was updated to match the interface changes made to the
00109  * ubi_BinTree module.  In particular, the interface to the Locate() function
00110  * has changed.  See ubi_BinTree for more information on changes and new
00111  * functions.
00112  *
00113  * The revision number was also upped to match ubi_BinTree.
00114  *
00115  * Revision 1.1  93/10/18  20:35:16  CRH
00116  * I removed the hard-coded logical device names from the include file
00117  * specifications.  CRH
00118  *
00119  * Revision 1.0  93/10/15  23:00:15  CRH
00120  * With this revision, I have added a set of #define's that provide a single,
00121  * standard API to all existing tree modules.  Until now, each of the three
00122  * existing modules had a different function and typedef prefix, as follows:
00123  *
00124  *       Module        Prefix
00125  *     ubi_BinTree     ubi_bt
00126  *     ubi_AVLtree     ubi_avl
00127  *     ubi_SplayTree   ubi_spt
00128  *
00129  * To further complicate matters, only those portions of the base module
00130  * (ubi_BinTree) that were superceeded in the new module had the new names.
00131  * For example, if you were using ubi_SplayTree, the locate function was
00132  * called "ubi_sptLocate", but the next and previous functions remained
00133  * "ubi_btNext" and "ubi_btPrev".
00134  *
00135  * This was not too terrible if you were familiar with the modules and knew
00136  * exactly which tree model you wanted to use.  If you wanted to be able to
00137  * change modules (for speed comparisons, etc), things could get messy very
00138  * quickly.
00139  *
00140  * So, I have added a set of defined names that get redefined in any of the
00141  * descendant modules.  To use this standardized interface in your code,
00142  * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with
00143  * "ubi_tr".  The "ubi_tr" names will resolve to the correct function or
00144  * datatype names for the module that you are using.  Just remember to
00145  * include the header for that module in your program file.  Because these
00146  * names are handled by the preprocessor, there is no added run-time
00147  * overhead.
00148  *
00149  * Note that the original names do still exist, and can be used if you wish
00150  * to write code directly to a specific module.  This should probably only be
00151  * done if you are planning to implement a new descendant type, such as
00152  * red/black trees.  CRH
00153  *
00154  * Revision 0.1  93/04/25  22:03:32  CRH
00155  * Simply changed the <exec/types.h> #include reference the .c file to
00156  * use <stdlib.h> instead.  The latter is portable, the former is not.
00157  *
00158  * Revision 0.0  93/04/21  23:05:52  CRH
00159  * Initial version, written by Christopher R. Hertel.
00160  * This module implements Splay Trees using the ubi_BinTree module as a basis.
00161  *
00162  * ========================================================================== **
00163  */
00164 
00165 #include "ubi_SplayTree.h"  /* Header for THIS module.   */
00166 
00167 /* ========================================================================== **
00168  * Static data.
00169  */
00170 
00171 static char ModuleID[] = "ubi_SplayTree\n\
00172 \t$Revision: 1.1 $\n\
00173 \t$Date: 2004/01/14 20:27:14 $\n\
00174 \t$Author: dwarren $\n";
00175 
00176 
00177 /* ========================================================================== **
00178  * Private functions...
00179  */
00180 
00181 static void Rotate( ubi_btNodePtr p )
00182   /* ------------------------------------------------------------------------ **
00183    * This function performs a single rotation, moving node *p up one level
00184    * in the tree.
00185    *
00186    *  Input:    p - a pointer to an ubi_btNode in a tree.
00187    *
00188    *  Output:   None.
00189    *
00190    *  Notes:    This implements a single rotation in either direction (left
00191    *            or right).  This is the basic building block of all splay
00192    *            tree rotations.
00193    * ------------------------------------------------------------------------ **
00194    */
00195   {
00196   ubi_btNodePtr parentp;
00197   ubi_btNodePtr tmp;
00198   char          way;
00199   char          revway;
00200 
00201   parentp = p->Link[ubi_trPARENT];    /* Find parent. */
00202 
00203   if( parentp )                 /* If no parent, then we're already the root. */
00204     {
00205     way    = p->gender;
00206     revway = ubi_trRevWay(way);
00207     tmp    = p->Link[(int)revway];
00208 
00209     parentp->Link[(int)way] = tmp;
00210     if( tmp )
00211       {
00212       tmp->Link[ubi_trPARENT] = parentp;
00213       tmp->gender             = way;
00214       }
00215 
00216     tmp                   = parentp->Link[ubi_trPARENT];
00217     p->Link[ubi_trPARENT] = tmp;
00218     p->gender             = parentp->gender;
00219     if( tmp )
00220       tmp->Link[(int)(p->gender)] = p;
00221 
00222     parentp->Link[ubi_trPARENT] = p;
00223     parentp->gender             = revway;
00224     p->Link[(int)revway]        = parentp;
00225     }
00226   } /* Rotate */
00227 
00228 static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe )
00229   /* ------------------------------------------------------------------------ **
00230    * Move the node indicated by SplayWithMe to the root of the tree by
00231    * splaying the tree.
00232    *
00233    *  Input:  SplayWithMe - A pointer to an ubi_btNode within a tree.
00234    *
00235    *  Output: A pointer to the root of the splay tree (i.e., the same as
00236    *          SplayWithMe).
00237    * ------------------------------------------------------------------------ **
00238    */
00239   {
00240   ubi_btNodePtr parent;
00241 
00242   while( NULL != (parent = SplayWithMe->Link[ubi_trPARENT]) )
00243     {
00244     if( parent->gender == SplayWithMe->gender )       /* Zig-Zig */
00245       Rotate( parent );
00246     else
00247       {
00248       if( ubi_trEQUAL != parent->gender )             /* Zig-Zag */
00249         Rotate( SplayWithMe );
00250       }
00251     Rotate( SplayWithMe );                            /* Zig */
00252     } /* while */
00253   return( SplayWithMe );
00254   } /* Splay */
00255 
00256 /* ========================================================================== **
00257  * Exported utilities.
00258  */
00259 
00260 ubi_trBool ubi_sptInsert( ubi_btRootPtr  RootPtr,
00261                           ubi_btNodePtr  NewNode,
00262                           ubi_btItemPtr  ItemPtr,
00263                           ubi_btNodePtr *OldNode )
00264   /* ------------------------------------------------------------------------ **
00265    * This function uses a non-recursive algorithm to add a new element to the
00266    * splay tree.
00267    *
00268    *  Input:   RootPtr  -  a pointer to the ubi_btRoot structure that indicates
00269    *                       the root of the tree to which NewNode is to be added.
00270    *           NewNode  -  a pointer to an ubi_btNode structure that is NOT
00271    *                       part of any tree.
00272    *           ItemPtr  -  A pointer to the sort key that is stored within
00273    *                       *NewNode.  ItemPtr MUST point to information stored
00274    *                       in *NewNode or an EXACT DUPLICATE.  The key data
00275    *                       indicated by ItemPtr is used to place the new node
00276    *                       into the tree.
00277    *           OldNode  -  a pointer to an ubi_btNodePtr.  When searching
00278    *                       the tree, a duplicate node may be found.  If
00279    *                       duplicates are allowed, then the new node will
00280    *                       be simply placed into the tree.  If duplicates
00281    *                       are not allowed, however, then one of two things
00282    *                       may happen.
00283    *                       1) if overwritting *is not* allowed, this
00284    *                          function will return FALSE (indicating that
00285    *                          the new node could not be inserted), and
00286    *                          *OldNode will point to the duplicate that is
00287    *                          still in the tree.
00288    *                       2) if overwritting *is* allowed, then this
00289    *                          function will swap **OldNode for *NewNode.
00290    *                          In this case, *OldNode will point to the node
00291    *                          that was removed (thus allowing you to free
00292    *                          the node).
00293    *                          **  If you are using overwrite mode, ALWAYS  **
00294    *                          ** check the return value of this parameter! **
00295    *                 Note: You may pass NULL in this parameter, the
00296    *                       function knows how to cope.  If you do this,
00297    *                       however, there will be no way to return a
00298    *                       pointer to an old (ie. replaced) node (which is
00299    *                       a problem if you are using overwrite mode).
00300    *
00301    *  Output:  a boolean value indicating success or failure.  The function
00302    *           will return FALSE if the node could not be added to the tree.
00303    *           Such failure will only occur if duplicates are not allowed,
00304    *           nodes cannot be overwritten, AND a duplicate key was found
00305    *           within the tree.
00306    * ------------------------------------------------------------------------ **
00307    */
00308   {
00309   ubi_btNodePtr OtherP;
00310 
00311   if( !(OldNode) )
00312     OldNode = &OtherP;
00313 
00314   if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) )
00315     {
00316     RootPtr->root = Splay( NewNode );
00317     return( ubi_trTRUE );
00318     }
00319 
00320   /* Splay the unreplacable, duplicate keyed, unique, old node. */
00321   RootPtr->root = Splay( (*OldNode) );
00322   return( ubi_trFALSE );
00323   } /* ubi_sptInsert */
00324 
00325 ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode )
00326   /* ------------------------------------------------------------------------ **
00327    * This function removes the indicated node from the tree.
00328    *
00329    *  Input:   RootPtr  -  A pointer to the header of the tree that contains
00330    *                       the node to be removed.
00331    *           DeadNode -  A pointer to the node that will be removed.
00332    *
00333    *  Output:  This function returns a pointer to the node that was removed
00334    *           from the tree (ie. the same as DeadNode).
00335    *
00336    *  Note:    The node MUST be in the tree indicated by RootPtr.  If not,
00337    *           strange and evil things will happen to your trees.
00338    * ------------------------------------------------------------------------ **
00339    */
00340   {
00341   ubi_btNodePtr p;
00342 
00343   (void)Splay( DeadNode );                  /* Move dead node to root.        */
00344   if( NULL != (p = DeadNode->Link[ubi_trLEFT]) )
00345     {                                       /* If left subtree exists...      */
00346     ubi_btNodePtr q = DeadNode->Link[ubi_trRIGHT];
00347 
00348     p->Link[ubi_trPARENT] = NULL;           /* Left subtree node becomes root.*/
00349     p->gender             = ubi_trPARENT;
00350     p                     = ubi_btLast( p );  /* Find rightmost left node...  */
00351     p->Link[ubi_trRIGHT]  = q;                /* ...attach right tree.        */
00352     if( q )
00353       q->Link[ubi_trPARENT] = p;
00354     RootPtr->root   = Splay( p );           /* Resplay at p.                  */
00355     }
00356   else
00357     {
00358     if( NULL != (p = DeadNode->Link[ubi_trRIGHT]) )
00359       {                               /* No left, but right subtree exists... */
00360       p->Link[ubi_trPARENT] = NULL;         /* Right subtree root becomes...  */
00361       p->gender       = ubi_trPARENT;       /* ...overall tree root.          */
00362       RootPtr->root   = p;
00363       }
00364     else
00365       RootPtr->root = NULL;                 /* No subtrees => empty tree.     */
00366     }
00367 
00368   (RootPtr->count)--;                       /* Decrement node count.          */
00369   return( DeadNode );                       /* Return pointer to pruned node. */
00370   } /* ubi_sptRemove */
00371 
00372 ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr,
00373                              ubi_btItemPtr FindMe,
00374                              ubi_trCompOps CompOp )
00375   /* ------------------------------------------------------------------------ **
00376    * The purpose of ubi_btLocate() is to find a node or set of nodes given
00377    * a target value and a "comparison operator".  The Locate() function is
00378    * more flexible and (in the case of trees that may contain dupicate keys)
00379    * more precise than the ubi_btFind() function.  The latter is faster,
00380    * but it only searches for exact matches and, if the tree contains
00381    * duplicates, Find() may return a pointer to any one of the duplicate-
00382    * keyed records.
00383    *
00384    *  Input:
00385    *     RootPtr  -  A pointer to the header of the tree to be searched.
00386    *     FindMe   -  An ubi_btItemPtr that indicates the key for which to
00387    *                 search.
00388    *     CompOp   -  One of the following:
00389    *                    CompOp     Return a pointer to the node with
00390    *                    ------     ---------------------------------
00391    *                   ubi_trLT - the last key value that is less
00392    *                              than FindMe.
00393    *                   ubi_trLE - the first key matching FindMe, or
00394    *                              the last key that is less than
00395    *                              FindMe.
00396    *                   ubi_trEQ - the first key matching FindMe.
00397    *                   ubi_trGE - the first key matching FindMe, or the
00398    *                              first key greater than FindMe.
00399    *                   ubi_trGT - the first key greater than FindMe.
00400    *  Output:
00401    *     A pointer to the node matching the criteria listed above under
00402    *     CompOp, or NULL if no node matched the criteria.
00403    *
00404    *  Notes:
00405    *     In the case of trees with duplicate keys, Locate() will behave as
00406    *     follows:
00407    *
00408    *     Find:  3                       Find: 3
00409    *     Keys:  1 2 2 2 3 3 3 3 3 4 4   Keys: 1 1 2 2 2 4 4 5 5 5 6
00410    *                  ^ ^         ^                   ^ ^
00411    *                 LT EQ        GT                 LE GE
00412    *
00413    *     That is, when returning a pointer to a node with a key that is LESS
00414    *     THAN the target key (FindMe), Locate() will return a pointer to the
00415    *     LAST matching node.
00416    *     When returning a pointer to a node with a key that is GREATER
00417    *     THAN the target key (FindMe), Locate() will return a pointer to the
00418    *     FIRST matching node.
00419    *
00420    *  See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf().
00421    * ------------------------------------------------------------------------ **
00422    */
00423   {
00424   ubi_btNodePtr p;
00425 
00426   p = ubi_btLocate( RootPtr, FindMe, CompOp );
00427   if( p )
00428     RootPtr->root = Splay( p );
00429   return( p );
00430   } /* ubi_sptLocate */
00431 
00432 ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr,
00433                            ubi_btItemPtr FindMe )
00434   /* ------------------------------------------------------------------------ **
00435    * This function performs a non-recursive search of a tree for any node
00436    * matching a specific key.
00437    *
00438    *  Input:
00439    *     RootPtr  -  a pointer to the header of the tree to be searched.
00440    *     FindMe   -  a pointer to the key value for which to search.
00441    *
00442    *  Output:
00443    *     A pointer to a node with a key that matches the key indicated by
00444    *     FindMe, or NULL if no such node was found.
00445    *
00446    *  Note:   In a tree that allows duplicates, the pointer returned *might
00447    *          not* point to the (sequentially) first occurance of the
00448    *          desired key.  In such a tree, it may be more useful to use
00449    *          ubi_sptLocate().
00450    * ------------------------------------------------------------------------ **
00451    */
00452   {
00453   ubi_btNodePtr p;
00454 
00455   p = ubi_btFind( RootPtr, FindMe );
00456   if( p )
00457     RootPtr->root = Splay( p );
00458   return( p );
00459   } /* ubi_sptFind */
00460 
00461 void ubi_sptSplay( ubi_btRootPtr RootPtr,
00462                    ubi_btNodePtr SplayMe )
00463   /* ------------------------------------------------------------------------ **
00464    *  This function allows you to splay the tree at a given node, thus moving
00465    *  the node to the top of the tree.
00466    *
00467    *  Input:
00468    *     RootPtr  -  a pointer to the header of the tree to be splayed.
00469    *     SplayMe  -  a pointer to a node within the tree.  This will become
00470    *                 the new root node.
00471    *  Output: None.
00472    *
00473    *  Notes:  This is an uncharacteristic function for this group of modules
00474    *          in that it provides access to the internal balancing routines,
00475    *          which would normally be hidden.
00476    *          Splaying the tree will not damage it (assuming that I've done
00477    *          *my* job), but there is overhead involved.  I don't recommend
00478    *          that you use this function unless you understand the underlying
00479    *          Splay Tree principles involved.
00480    * ------------------------------------------------------------------------ **
00481    */
00482   {
00483   RootPtr->root = Splay( SplayMe );
00484   } /* ubi_sptSplay */
00485 
00486 int ubi_sptModuleID( int size, char *list[] )
00487   /* ------------------------------------------------------------------------ **
00488    * Returns a set of strings that identify the module.
00489    *
00490    *  Input:  size  - The number of elements in the array <list>.
00491    *          list  - An array of pointers of type (char *).  This array
00492    *                  should, initially, be empty.  This function will fill
00493    *                  in the array with pointers to strings.
00494    *  Output: The number of elements of <list> that were used.  If this value
00495    *          is less than <size>, the values of the remaining elements are
00496    *          not guaranteed.
00497    *
00498    *  Notes:  Please keep in mind that the pointers returned indicate strings
00499    *          stored in static memory.  Don't free() them, don't write over
00500    *          them, etc.  Just read them.
00501    * ------------------------------------------------------------------------ **
00502    */
00503   {
00504   if( size > 0 )
00505     {
00506     list[0] = ModuleID;
00507     if( size > 1 )
00508       return( 1 + ubi_btModuleID( --size, &(list[1]) ) );
00509     return( 1 );
00510     }
00511   return( 0 );
00512   } /* ubi_sptModuleID */
00513 
00514 /* ================================ The End ================================= */
00515 

Generated on Wed Jul 26 13:30:43 2006 for XSB by  doxygen 1.4.5