home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3148 / avl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-29  |  23.9 KB  |  786 lines

  1. /**
  2. *
  3. * avl.c -- C source file for avl trees. Contains the auxillary routines
  4. *          and defines for the avl tree functions and user interface and
  5. *          includes all the necessary public and private routines
  6. *
  7. * Created 03/01/89 by Brad Appleton
  8. *
  9. * ^{Mods:* }
  10. * Fri Jul 14 13:53:42 1989, Rev 1.0, brad(0165)
  11. *
  12. **/
  13.  
  14.     /* some common #defines used throughout most of my files */
  15. #define  PUBLIC   /* default */
  16. #define  PRIVATE  static
  17. #define  FALSE    0
  18. #define  TRUE     !FALSE
  19.   
  20.     /* some defines for debugging purposes */
  21. #ifdef NDEBUG
  22. #define DBG(x)        /* x */
  23. #else
  24. #define DBG(x)        x
  25. #endif
  26.  
  27. #define  NEXTERN   /* dont include "extern" declarations from header files */
  28.  
  29. #include  <stdio.h>
  30. #include  "avl.h"         /* public types for avl trees */
  31. #include  "avl_typs.h"    /* private types for avl trees */
  32.  
  33.  
  34.  
  35. /************************************************************************
  36. *    Auxillary functions
  37. *
  38. *    routines to allocate/de-allocate an AVL node,
  39. *       and determine the type of an AVL node.
  40. ************************************************************************/
  41.  
  42. /* ckalloc( size ) -- allocate space; check for success */
  43. PRIVATE     char *ckalloc( size )
  44. int size;
  45. {
  46.     char *malloc(), *ptr;
  47.   
  48.     if ( (ptr = malloc(  (unsigned) size)) == NULL )  {
  49.         fprintf( stderr, "Unable to allocate storage." );
  50.         exit( 1 );
  51.     }/* if */
  52.   
  53.     return  ptr;
  54. }/* ckalloc */
  55.  
  56.  
  57. /*
  58. * new_node() -- get space for a new node and its data;
  59. *               return the address of the new node
  60. */
  61. PRIVATE   AVLtree  new_node( data, size )
  62. void     *data;
  63. unsigned  size;
  64. {
  65.     AVLtree  root;
  66.   
  67.     root = (AVLtree) ckalloc( sizeof (AVLnode) );
  68.     root -> data = (void *) ckalloc( size );
  69.     memcpy( root -> data, data, size );
  70.     root -> bal  = BALANCED;
  71.     root -> subtree[ LEFT ]  = root -> subtree[ RIGHT ] = NULL_TREE;
  72.   
  73.     return  root;
  74. }/* new_node */
  75.  
  76.  
  77. /*
  78. * free_node()  --  free space for a node and its data!
  79. *                  reset the node pointer to NULL
  80. */
  81. PRIVATE    void free_node( rootp )
  82. AVLtree     *rootp;
  83. {
  84.     free( (void *) *rootp );
  85.     *rootp = NULL_TREE;
  86. }/* free_node */
  87.   
  88.   
  89. /*
  90. * node_type() -- determine the number of null pointers for a given
  91. *                node in an AVL tree, Returns a value of type NODE
  92. *                which is an enumeration type with the following values:
  93. *
  94. *                  IS_TREE     --  both subtrees are non-empty
  95. *                  IS_LBRANCH  --  left subtree is non-empty; right is empty
  96. *                  IS_RBRANCH  --  right subtree is non-empty; left is empty
  97. *                  IS_LEAF     --  both subtrees are empty
  98. *                  IS_NULL     --  given tree is empty
  99. */
  100. PRIVATE     NODE node_type( tree )
  101. AVLtree    tree;
  102. {
  103.     if ( tree == NULL_TREE )
  104.         return  IS_NULL;
  105.   
  106.     else if ( (tree -> subtree[ LEFT ] != NULL_TREE)  &&  (tree -> subtree[ RIGHT ] != NULL_TREE) )
  107.         return  IS_TREE;
  108.   
  109.     else if ( tree -> subtree[ LEFT ] != NULL_TREE )
  110.         return  IS_LBRANCH;
  111.   
  112.     else if ( tree -> subtree[ RIGHT ] != NULL_TREE )
  113.         return  IS_RBRANCH;
  114.   
  115.     else
  116.     return  IS_LEAF;
  117. }/* node_type */
  118.  
  119.  
  120.  
  121. /************************************************************************
  122. *    PRIVATE functions for manipulating AVL trees
  123. *
  124. *  This following defines a set of routines for creating, maintaining, and
  125. *  manipulating AVL Trees as an Abtract Data Type. The routines in this
  126. *  file that are accessible (through the avl tree user-interface) to other
  127. *  files to allow other programmers to:
  128. *
  129. *       Insert, Delete, and Find a given data item from a Tree.
  130. *
  131. *       Delete and Find the minimal and Maximal items in a Tree.
  132. *
  133. *       Walk through every node in a tree performing a giving operation.
  134. *
  135. *       Walk through and free up space for every node in a tree while performing
  136. *       a given operation on the data items as they are encountered.
  137. ************************************************************************/
  138.  
  139.  
  140.  
  141. /************************************************************************
  142. *    routines used to find the minimal and maximal elements
  143. *       (nodes) of an AVL tree.
  144. ************************************************************************/
  145.   
  146. /*
  147. * avl_min() -- compare function used to find the minimal element in a tree
  148. */
  149. PRIVATE int avl_min( elt1, elt2, nd_typ )
  150. void  *elt1, *elt2;
  151. NODE  nd_typ;
  152. {
  153.     if ( nd_typ == IS_RBRANCH  ||  nd_typ == IS_LEAF )
  154.         return   0;   /* left subtree is empty -- this is the minimum */
  155.     
  156.     else  return  -1;   /* keep going left */
  157. }/* avl_min */
  158.  
  159.  
  160. /*
  161. * avl_max() -- compare function used to find the maximal element in a tree
  162. */
  163. PRIVATE int avl_max( elt1, elt2, nd_typ )
  164. void  *elt1, *elt2;
  165. NODE  nd_typ;
  166. {
  167.     if ( nd_typ == IS_RBRANCH  ||  nd_typ == IS_LEAF )
  168.         return  0;   /* right subtree is empty -- this is the maximum */
  169.     
  170.     else  return  1;   /* keep going right */
  171. }/* avl_max */
  172.  
  173.  
  174.  
  175. /************************************************************************
  176. *    Routines to perform rotations on AVL trees
  177. ************************************************************************/
  178.  
  179. /*
  180. * rotate_once()  --  rotate a given node in the given direction
  181. *                    to restore the balance of a tree
  182. */
  183. PRIVATE     short rotate_once( rootp, dir )
  184. AVLtree    *rootp;
  185. DIRECTION  dir;
  186. {
  187.     DIRECTION   other_dir = OPPOSITE( dir );    /* opposite direction to "dir" */
  188.     AVLtree     old_root  = *rootp;        /* copy of original root of tree */
  189.     short    ht_unchanged;            /* true if height unchanged */
  190.  
  191.     ht_unchanged = ( (*rootp) -> subtree[ other_dir ] -> bal ) ? FALSE : TRUE;
  192.   
  193.         /* assign new root */
  194.     *rootp = old_root -> subtree[ other_dir ];
  195.   
  196.         /* new-root exchanges it's "dir" subtree for it's parent */
  197.     old_root -> subtree[ other_dir ]   =   (*rootp) -> subtree[ dir ];
  198.     (*rootp) -> subtree[ dir ]         =   old_root;
  199.   
  200.         /* update balances */
  201.     old_root -> bal = -( dir == LEFT ? --( (*rootp) -> bal ) : ++( (*rootp) -> bal )  );
  202.   
  203.     return  ht_unchanged;
  204. }/* rotate_once */
  205.   
  206.   
  207. /*
  208. * rotate_twice()  --  rotate a given node in the given direction
  209. *                     and then in the opposite direction
  210. *                     to restore the balance of a tree
  211. */
  212. PRIVATE     void rotate_twice( rootp, dir )
  213. AVLtree    *rootp;
  214. DIRECTION  dir;
  215. {
  216.     DIRECTION   other_dir        = OPPOSITE( dir );
  217.     AVLtree     old_root        = *rootp,
  218.                 old_other_dir_subtree    = (*rootp) -> subtree[ other_dir ];
  219.     
  220.         /* assign new root */
  221.     *rootp = old_root -> subtree[ other_dir ] -> subtree[ dir ];
  222.   
  223.         /* new-root exchanges it's "dir" subtree for it's grandparent */
  224.     old_root -> subtree[ other_dir ]  =   (*rootp) -> subtree[ dir ];
  225.     (*rootp) -> subtree[ dir ]        =   old_root;
  226.   
  227.         /* new-root exchanges it's "other-dir" subtree for it's parent */
  228.     old_other_dir_subtree -> subtree[ dir ]    =   (*rootp) -> subtree[ other_dir ];
  229.     (*rootp) -> subtree[ other_dir ]        =   old_other_dir_subtree;
  230.   
  231.         /* update balances */
  232.     (*rootp) -> subtree[ LEFT ] -> bal   =  -MAX( (*rootp) -> bal, 0 );
  233.     (*rootp) -> subtree[ RIGHT ] -> bal  =  -MIN( (*rootp) -> bal, 0 );
  234.     (*rootp) -> bal                      =  0;
  235.  
  236. }/* rotate_twice */
  237.  
  238.  
  239. /************************************************************************
  240. *                    Rebalance an AVL tree
  241. ************************************************************************/
  242.  
  243. /*
  244. * balance()  --  determines and performs the  sequence of rotations needed
  245. *                   (if any) to restore the balance of a given tree.
  246. *
  247. *     Returns 1 if tree height changed due to rotation; 0 otherwise
  248. */
  249. PRIVATE    short  balance( rootp )
  250. AVLtree    *rootp;
  251. {
  252.     short  special_case = FALSE;
  253.  
  254.     if ( LEFT_IMBALANCE( *rootp )  )  {   /* need a right rotation */
  255.         if ( (*rootp) -> subtree[ LEFT ] -> bal  ==  RIGHT_HEAVY )
  256.             rotate_twice( rootp, RIGHT );    /* double RL rotation needed */
  257.  
  258.         else    /* single RR rotation needed */
  259.             special_case = rotate_once( rootp, RIGHT );
  260.     }/* if */
  261.   
  262.     else if ( RIGHT_IMBALANCE( *rootp )  )  {   /* need a left rotation */
  263.         if ( (*rootp) -> subtree[ RIGHT ] -> bal  ==  LEFT_HEAVY )
  264.             rotate_twice( rootp, LEFT );     /* double LR rotation needed */
  265.  
  266.         else    /* single LL rotation needed */
  267.             special_case = rotate_once( rootp, LEFT );
  268.     }/* elif */
  269.   
  270.     else  return  HEIGHT_UNCHANGED;    /* no rotation occurred */
  271.   
  272.     return  ( special_case ) ? HEIGHT_UNCHANGED : HEIGHT_CHANGED;
  273. }/* balance */
  274.  
  275.  
  276. /************************************************************************
  277. *    Routines to:    Find an item in an AVL tree
  278. *            Insert an item into an AVL tree
  279. *            Delete an item from an AVL tree
  280. ************************************************************************/
  281.  
  282. /*
  283. * avl_find() -- find an item in the given tree
  284. *
  285. *   PARAMETERS:
  286. *                data       --  a pointer to the key to find
  287. *                rootp      --  a pointer to an AVL tree
  288. *                compar     --  name of a function to compare 2 data items
  289. */
  290. PRIVATE      void *avl_find( data, tree, compar )
  291. void      *data;
  292. AVLtree   tree;
  293. int       (*compar)();
  294. {
  295.     NODE       nd_typ = node_type( tree );
  296.     int        cmp;
  297.   
  298.     while ( (cmp = (*compar)( data, tree -> data, nd_typ ))  &&
  299.         (tree != NULL_TREE) )
  300.         tree = tree -> subtree[ (cmp < 0) ? LEFT : RIGHT ];
  301.   
  302.     return  ( tree == NULL_TREE ) ? NULL : tree -> data;
  303. }/* avl_find */
  304.   
  305.  
  306. /*
  307. * avl_insert() -- insert an item into the given tree
  308. *
  309. *   PARAMETERS:
  310. *                data       --  a pointer to a pointer to the data to add;
  311. *                               On exit, *data is NULL if insertion succeeded,
  312. *                               otherwise address of the duplicate key
  313. *                rootp      --  a pointer to an AVL tree
  314. *                compar     --  name of the function to compare 2 data items
  315. */
  316. PRIVATE     short avl_insert( data, size, rootp, compar )
  317. void     **data;
  318. unsigned size;
  319. AVLtree  *rootp;
  320. int      (*compar)();
  321. {
  322.     short increase;
  323.     int   cmp;
  324.   
  325.     if ( *rootp == NULL_TREE )  {  /* insert new node here */
  326.         *rootp = new_node( *data, size );
  327.         *data  = NULL;     /* set return value in data */
  328.         return  HEIGHT_CHANGED;
  329.     }/* if */
  330.   
  331.     cmp = (*compar)( *data, (*rootp) -> data );   /* compare data items */
  332.   
  333.     if ( cmp < 0 )  {  /* insert into the left subtree */
  334.         increase =  -avl_insert( data, size, &( (*rootp) -> subtree[ LEFT ] ), compar );
  335.         if ( *data != NULL )     return  HEIGHT_UNCHANGED;
  336.     }/* elif */
  337.   
  338.     else if ( cmp > 0 )  {  /* insert into the right subtree */
  339.         increase =  avl_insert( data, size, &( (*rootp) -> subtree[ RIGHT ] ), compar );
  340.         if ( *data != NULL )     return  HEIGHT_UNCHANGED;
  341.     }/* elif */
  342.   
  343.     else  {   /* data already exists */
  344.         *data = (*rootp) -> data;   /* set return value in data */
  345.         return  HEIGHT_UNCHANGED;
  346.     } /* else */
  347.   
  348.     (*rootp) -> bal += increase;    /* update balance factor */
  349.  
  350.   /************************************************************************
  351.   * re-balance if needed -- height of current tree increases only if its
  352.   * subtree height increases and the current tree needs no rotation.
  353.   ************************************************************************/
  354.     if ( increase  &&  (*rootp) -> bal )
  355.         return  (  1 - balance( rootp )  );
  356.     else
  357.         return  HEIGHT_UNCHANGED;
  358. }/* avl_insert */
  359.  
  360.  
  361. /*
  362. * avl_delete() -- delete an item from the given tree
  363. *
  364. *   PARAMETERS:
  365. *                data       --  a pointer to a pointer to the key to delete
  366. *                               On exit, *data points to the deleted data item
  367. *                               (or NULL if deletion failed).
  368. *                rootp      --  a pointer to an AVL tree
  369. *                compar     --  name of function to compare 2 data items
  370. */
  371. PRIVATE     short avl_delete( data, rootp, compar )
  372. void      **data;
  373. AVLtree   *rootp;
  374. int       (*compar)();
  375. {
  376.     short      decrease;
  377.     int        cmp;
  378.     AVLtree    old_root  = *rootp;
  379.     NODE       nd_typ    = node_type( *rootp );
  380.     DIRECTION  dir       = (nd_typ == IS_LBRANCH) ? LEFT : RIGHT;
  381.   
  382.     if ( *rootp == NULL_TREE )  {  /* data not found */
  383.         *data = NULL;    /* set return value in data */
  384.         return  HEIGHT_UNCHANGED;
  385.     }/* if */
  386.   
  387.     cmp = compar( *data, (*rootp) -> data, nd_typ );   /* compare data items */
  388.   
  389.     if ( cmp < 0 )  {  /* delete from left subtree */
  390.         decrease =  -avl_delete( data, &( (*rootp) -> subtree[ LEFT ] ), compar );
  391.         if ( *data == NULL )     return  HEIGHT_UNCHANGED;
  392.     }/* elif */
  393.   
  394.     else if ( cmp > 0 )  {  /* delete from right subtree */
  395.         decrease =  avl_delete( data, &( (*rootp) -> subtree[ RIGHT ] ), compar );
  396.         if ( *data == NULL )     return  HEIGHT_UNCHANGED;
  397.     }/* elif */
  398.     
  399.   /************************************************************************
  400.   *  At this point we know that if "cmp" is zero then "*rootp" points to
  401.   *  the node that we need to delete.  There are three cases:
  402.   *
  403.   *     1) The node is a leaf.  Remove it and return.
  404.   *
  405.   *     2) The node is a branch (has only 1 child). Make "*rootp"
  406.   *        (the pointer to this node) point to the child.
  407.   *
  408.   *     3) The node has two children. We swap data with the successor of
  409.   *        "*rootp" (the smallest item in its right subtree) and delete
  410.   *        the successor from the right subtree of "*rootp".  The
  411.   *        identifier "decrease" should be reset if the subtree height
  412.   *        decreased due to the deletion of the sucessor of "rootp".
  413.   ************************************************************************/
  414.   
  415.     else  {  /* cmp == 0 */
  416.         *data = (*rootp) -> data;  /* set return value in data */
  417.   
  418.         switch ( nd_typ )  {  /* what kind of node are we removing? */
  419.             case  IS_LEAF :
  420.             free_node( rootp );          /* free the leaf, its height     */
  421.                 return  HEIGHT_CHANGED;      /* changes from 1 to 0, return 1 */
  422.   
  423.             case  IS_RBRANCH :       /* only child becomes new root */
  424.             case  IS_LBRANCH :
  425.             *rootp = (*rootp) -> subtree[ dir ];
  426.                 free_node( &old_root );      /* free the deleted node */
  427.                 return  HEIGHT_CHANGED;      /* we just shortened the "dir" subtree */
  428.   
  429.             case  IS_TREE  :
  430.                 decrease = avl_delete(  &( (*rootp) -> data ),
  431.                                         &( (*rootp) -> subtree[ RIGHT ] ),
  432.                                         avl_min                );
  433.         } /* switch */
  434.     } /* else */
  435.  
  436.     (*rootp) -> bal -= decrease;       /* update balance factor */
  437.   
  438.   /**********************************************************************
  439.   * Rebalance if necessary -- the height of current tree changes if one
  440.   * of two things happens: (1) a rotation was performed which changed
  441.   * the height of the subtree (2) the subtree height decreased and now
  442.   * matches the height of its other subtree (so the current tree now
  443.   * has a zero balance when it previously did not).
  444.   **********************************************************************/
  445.     if ( decrease  &&  (*rootp) -> bal )    /* return 1 if height      */
  446.         return  balance( rootp );        /* changed due to rotation */
  447.   
  448.     else if ( decrease  && !(*rootp) -> bal )    /* or if balance is 0 from    */
  449.         return  HEIGHT_CHANGED;            /* height decrease of subtree */
  450.   
  451.     else
  452.         return  HEIGHT_UNCHANGED;
  453.   
  454. }/* avl_delete */
  455.  
  456.  
  457.  
  458. /**
  459. *    Routines which Recursively Traverse an AVL TREE
  460. *
  461. * These routines may perform a particular action function upon each node
  462. * encountered. In these cases, "action" has the following definition:
  463. *
  464. *   void action( data, order, node, level, bal )
  465. *       void   *data
  466. *       VISIT   order;
  467. *       NODE    node;
  468. *    short    bal;
  469. *       int     level;
  470. *
  471. *         "data"    is a pointer to the data field of an AVL node
  472. *         "order"   corresponds to whether this is the 1st, 2nd or 3rd time
  473. *                   that this node has been visited.
  474. *         "node"    indicates which children (if any) of the current node
  475. *                   are null.
  476. *         "level"   is the current level (or depth) in the tree of the
  477. *                   curent node.
  478. *         "bal"     is the balance factor of the current node.
  479. **/
  480.  
  481.  
  482. /************************************************************************
  483. *    Walk an AVL tree, performing a given function at each node
  484. ************************************************************************/
  485.  
  486.  
  487. /*
  488. * avl_walk -- traverse the given tree performing "action"
  489. *            upon each data item encountered.
  490. *
  491. */
  492. PRIVATE     void  avl_walk( tree, action, sibling_order, level )
  493. AVLtree        tree;
  494. void           (*action)();
  495. SIBLING_ORDER  sibling_order;
  496. int            level;
  497. {
  498.     DIRECTION  dir1 = (sibling_order == LEFT_TO_RIGHT) ? LEFT : RIGHT,
  499.                dir2 = OPPOSITE( dir1 );
  500.     NODE       node = node_type( tree );
  501.   
  502.     if ( (tree != NULL_TREE)  &&  (action != NULL_ACTION) )  {
  503.         (*action)( tree -> data, PREORDER, node, level, tree -> bal );
  504.   
  505.         if ( tree -> subtree[ dir1 ]  !=  NULL_TREE )
  506.             avl_walk( tree -> subtree[ dir1 ], action, sibling_order, level+1 );
  507.   
  508.         (*action)( tree -> data, INORDER, node, level, tree -> bal );
  509.   
  510.         if ( tree -> subtree[ dir2 ]  !=  NULL_TREE )
  511.             avl_walk( tree -> subtree[ dir2 ], action, sibling_order, level+1 );
  512.   
  513.         (*action)( tree -> data, POSTORDER, node, level, tree -> bal );
  514.     }/* if non-empty tree */
  515.   
  516. }/* avl_walk */
  517.  
  518.  
  519.  
  520. /************************************************************************
  521. *    Walk an AVL tree, de-allocating space for each node
  522. *       and performing a given function at each node
  523. *       (such as de-allocating the user-defined data item).
  524. ************************************************************************/
  525.  
  526.  
  527. /*
  528. * avl_free() -- free up space for all nodes in a given tree
  529. *              performing "action" upon each data item encountered.
  530. *
  531. *    (only perform "action" if it is a non-null function) 
  532. */
  533.  
  534. PRIVATE     void  avl_free( rootp, action, sibling_order, level )
  535. AVLtree        *rootp;
  536. void           (*action)();
  537. SIBLING_ORDER  sibling_order;
  538. int            level;
  539. {
  540.     DIRECTION  dir1 = (sibling_order == LEFT_TO_RIGHT) ? LEFT : RIGHT,
  541.                dir2 = OPPOSITE( dir1 );
  542.     NODE       node = node_type( *rootp );
  543.   
  544.     if ( *rootp != NULL_TREE )  {
  545.   
  546.         if ( action != NULL_ACTION )
  547.        (*action)( (*rootp) -> data, PREORDER, node, level );
  548.   
  549.         if ( (*rootp) -> subtree[ dir1 ]  !=  NULL_TREE )
  550.             avl_free( &( (*rootp) -> subtree[ dir1 ] ),
  551.             action, sibling_order, level+1 );
  552.   
  553.         if ( action != NULL_ACTION )
  554.        (*action)( (*rootp) -> data, INORDER, node, level );
  555.   
  556.         if ( (*rootp) -> subtree[ dir2 ]  !=  NULL_TREE )
  557.             avl_free( &( (*rootp) -> subtree[ dir2 ] ),
  558.             action, sibling_order, level+1 );
  559.   
  560.         if ( action != NULL_ACTION )
  561.        (*action)( (*rootp) -> data, POSTORDER, node, level );
  562.   
  563.         free( *rootp );
  564.     }/* if non-empty tree */
  565.   
  566. }/* avl_free */
  567.  
  568.  
  569.  
  570.  
  571. /**********************************************************************
  572. *        C-interface (public functions) for avl trees 
  573. *
  574. *    These are the functions that are visible to the user of the
  575. *    AVL Tree Library. Mostly they just return or modify a
  576. *    particular attribute, or Call a private functions with the
  577. *    given parameters.
  578. *
  579. *    Note that public routine names begin with "avl" whereas
  580. *    private routine names that are called by public routines
  581. *    begin with "avl_" (the underscore character is added).
  582. *
  583. *    Each public routine must convert (cast) any argument of the 
  584. *    public type "AVL_TREE" to a pointer to on object of the 
  585. *    private type "AVLdescriptor" before passing the actual 
  586. *    AVL tree to any of the private routines. In this way, the
  587. *    type "AVL_TREE" is implemented as an opaque type.
  588. *    An "AVLdescriptor" is merely a container for AVL-tree
  589. *    objects which contains the pointer to the root of the 
  590. *    tree and the various attributes of the tree.
  591. *
  592. *    The function types prototypes for the routines which follow
  593. *    are declared in the include file "avl.h"
  594. *
  595. ***********************************************************************/
  596.  
  597.  
  598.  
  599. /*
  600. * avlinit() -- get space for an AVL descriptor for the given tree
  601. *              structure and initialize its fields.
  602. */
  603. PUBLIC AVL_TREE   avlinit( compar, isize )
  604. int       (*compar) ();
  605. unsigned  (*isize) ();
  606. {
  607.     AVLdescriptor  *avl_desc;
  608.   
  609.     avl_desc = (AVLdescriptor *) ckalloc( sizeof (AVLdescriptor) );
  610.     avl_desc -> root    = NULL_TREE;
  611.     avl_desc -> compar    = compar;
  612.     avl_desc -> isize    = isize;
  613.     avl_desc -> count    = 0;
  614.   
  615.     return  (AVL_TREE) avl_desc;
  616. }/* avlinit */
  617.  
  618.  
  619.  
  620. /*
  621. * avldispose() -- free up all space associated with the given tree structure.
  622. */
  623. PUBLIC void   avldispose( treeptr, action, sibling_order )
  624. AVL_TREE       *treeptr;
  625. void           (*action) ();
  626. SIBLING_ORDER  sibling_order;
  627. {
  628.     AVLdescriptor  *avl_desc;
  629.   
  630.     avl_desc = (AVLdescriptor *) *treeptr;
  631.     avl_free( &(avl_desc -> root), action, sibling_order, 1 );
  632.     *treeptr = (AVL_TREE) NULL;
  633. }/* avldispose */
  634.  
  635.  
  636.  
  637. /*
  638. * avlwalk() -- traverse the given tree structure and perform the
  639. *              given action on each data item in the tree.
  640. */
  641. PUBLIC void   avlwalk( tree, action, sibling_order )
  642. AVL_TREE       tree;
  643. void           (*action)();
  644. SIBLING_ORDER  sibling_order;
  645. {
  646.     AVLdescriptor  *avl_desc;
  647.   
  648.     avl_desc = (AVLdescriptor *) tree;
  649.     avl_walk( avl_desc -> root, action, sibling_order, 1 );
  650. }/* avlwalk */
  651.   
  652.    
  653.  
  654. /*
  655. * avlcount () --  return the number of nodes in the given tree
  656. */
  657. PUBLIC int  avlcount( tree )
  658. AVL_TREE  tree;
  659. {
  660.     AVLdescriptor  *avl_desc;
  661.   
  662.     avl_desc = (AVLdescriptor *) tree;
  663.     return  avl_desc -> count;
  664. }/* avlcount */
  665.  
  666.  
  667.  
  668. /*
  669. * avlins() -- insert the given item into the tree structure
  670. */
  671. PUBLIC void  *avlins( data, tree )
  672. void      *data;
  673. AVL_TREE  tree;
  674. {
  675.     AVLdescriptor  *avl_desc;
  676.   
  677.     avl_desc = (AVLdescriptor *) tree;
  678.     avl_insert( &data, (*(avl_desc -> isize))( data ), &(avl_desc -> root), avl_desc -> compar );
  679.     if ( data == NULL )    ++(avl_desc -> count);
  680.  
  681.     return  data;
  682. }/* avlins */
  683.  
  684.  
  685.  
  686. /*
  687. * avldel() -- delete the given item from the given tree structure
  688. */
  689. PUBLIC void  *avldel( data, tree )
  690. void      *data;
  691. AVL_TREE  tree;
  692. {
  693.     AVLdescriptor  *avl_desc;
  694.   
  695.     avl_desc = (AVLdescriptor *) tree;
  696.     avl_delete( &data, &(avl_desc -> root), avl_desc -> compar );
  697.     if ( data != NULL )     --(avl_desc -> count);
  698.   
  699.     return  data;
  700. }/* avldel */
  701.  
  702.  
  703.  
  704. /*
  705. * avlfind() -- find the given item in the given tree structure
  706. *              and return its address (NULL if not found).
  707. */
  708. PUBLIC void  *avlfind( data, tree )
  709. void      *data;
  710. AVL_TREE  tree;
  711. {
  712.     AVLdescriptor  *avl_desc;
  713.   
  714.     avl_desc = (AVLdescriptor *) tree;
  715.     return  avl_find( data, &(avl_desc -> root), avl_desc -> compar );
  716. }/* avlfind */
  717.  
  718.   
  719.  
  720. /*
  721. * avldelmin() -- delete the minimal item from the given tree structure
  722. */
  723. PUBLIC void  *avldelmin( tree )
  724. AVL_TREE  tree;
  725. {
  726.     void  *data;
  727.     AVLdescriptor  *avl_desc;
  728.   
  729.     avl_desc = (AVLdescriptor *) tree;
  730.     avl_delete( &data, &(avl_desc -> root), avl_min );
  731.     if ( data != NULL )     --(avl_desc -> count);
  732.   
  733.     return  data;
  734. }/* avldelmin */
  735.  
  736.  
  737.  
  738. /*
  739. * avlfindmin() -- find the minimal item in the given tree structure
  740. *              and return its address (NULL if not found).
  741. */
  742. PUBLIC void  *avlfindmin( tree )
  743. AVL_TREE  tree;
  744. {
  745.     AVLdescriptor  *avl_desc;
  746.   
  747.     avl_desc = (AVLdescriptor *) tree;
  748.     return  avl_find( NULL, &(avl_desc -> root), avl_min );
  749. }/* avlfindmin */
  750.  
  751.   
  752.  
  753. /*
  754. * avldelmax() -- delete the maximal item from the given tree structure
  755. */
  756. PUBLIC void  *avldelmax( tree )
  757. AVL_TREE  tree;
  758. {
  759.     void  *data;
  760.     AVLdescriptor  *avl_desc;
  761.   
  762.     avl_desc = (AVLdescriptor *) tree;
  763.     avl_delete( &data, &(avl_desc -> root), avl_max );
  764.     if ( data != NULL )     --(avl_desc -> count);
  765.   
  766.     return  data;
  767. }/* avldelmax */
  768.  
  769.   
  770.  
  771. /*
  772. * avlfindmax() -- find the maximal item in the given tree structure
  773. *              and return its address (NULL if not found).
  774. */
  775. PUBLIC void  *avlfindmax (tree)
  776. AVL_TREE  tree;
  777. {
  778.     AVLdescriptor  *avl_desc;
  779.   
  780.     avl_desc = (AVLdescriptor *) tree;
  781.     return  avl_find( NULL, &(avl_desc -> root), avl_max );
  782. }/* avlfindmax */
  783.