avlLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:41k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* avlLib.c - AVL trees library */
  2. /* Copyright 1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01e,10feb00,abd added avlMinimumGet and avlMaximumGet
  8. 01d,10feb00,abd added avlTreeWalk, avlTreePrint, avlTreeErase, avlTreePrintErase
  9. 01c,03feb00,abd added avlInsertInform, avlRemoveInsert
  10. 01b,24jan00,abd added avlSuccessorGet and avlPredecessorGet
  11. 01a,08feb99,wkn  created.
  12. */
  13. /*
  14. DESCRIPTION
  15. This library provides routines to manage some partially-balanced binary trees
  16. using the AVL algorithm. The tree nodes are ordered according to a given fully
  17. ordered relation, and there cannot be two nodes in the tree that are considered
  18. as equals by this relation. A balancing algorithm is run after each insertion
  19. or deletion operation. The balancing algorithm is guaranteed to run in time
  20. proportional to the height of the tree, and this height is guaranteed to only
  21. grow with log(N) where N is the number of nodes in the tree. Thus searching,
  22. insertion and deletion are all guaranteed to run in time proportional to
  23. log(N).
  24. Because the rebalancing operation might require re-rooting the binary tree,
  25. the arguments to the insertion and deletion operations cannot be simply
  26. pointers to the root node but they need to be pointers to the root node
  27. pointer. This way the root node pointer can be modified when the binary tree
  28. is re-rooted.
  29. In order to save some memory, the tree nodes does not contains pointers to
  30. their parent node. However, the rebalancing operation needs to walk from a
  31. given node up to the root node. We thus expect the insertion and deletion
  32. routines to keep track of the path they followed from the root down to the
  33. leaf node they had to insert or delete. See the avlRebalance routine for more
  34. details about this, and the avlInsert and avlDelete routines for reference
  35. implementations.
  36. It is an implementation goal to allow the creation of AVL trees containing
  37. some various data types in their nodes. However, the searching, insertion,
  38. and deletion routines needs to be able to compare two data nodes, so they
  39. are dependant upon the precise type of the search keys. The implementation of
  40. avlSearch, avlInsert and avlDelete uses a user-provided function that compares
  41. a tree node with a value and returns -1, 0 or 1 depending if this value is
  42. inferior, equal or superior to the key of the tree node. The value that is
  43. passed to this comparison function is typed as a GENERIC_ARGUMENT, which is a
  44. C union of an integer and a void pointer, thus making argument passing both
  45. fast and generic.
  46. INTERNAL
  47. For cases where execution speed is more important than code size, one could
  48. also use his own specialized routines instead of avlInsert, avlDelete and/or
  49. avlSearch, where the comparison function would be hardcoded to suit the user's
  50. needs. If one decides to do so, he can still use the generic avlRebalance
  51. routine because thisone does not needs to use a comparison function.
  52. INCLUDE FILE: avlLib.h
  53. */
  54. /* includes */
  55. #include <vxWorks.h>
  56. #include <stdlib.h>
  57. #include <stdio.h>
  58. #include "avlLib.h"
  59. /* typedefs */
  60. typedef struct
  61.     {
  62.     AVL_NODE    avl;
  63.     UINT        key;
  64.     } AVL_UNSIGNED_NODE;
  65. /* defines */
  66. #define AVL_MAX_HEIGHT 42 /* The meaning of life, the universe and everything.
  67.                  Plus, the nodes for a tree this high would use
  68.                  more than 2**32 bytes anyway */
  69. /*******************************************************************************
  70. *
  71. * avlRebalance - make sure the tree conforms to the AVL balancing rules, while
  72. * preserving the ordering of the binary tree
  73. *
  74. * INTERNAL
  75. * The AVL tree balancing rules are as follows :
  76. * - the height of the left and right subtrees under a given node must never
  77. *   differ by more than one
  78. * - the height of a given subtree is defined as 1 plus the maximum height of
  79. *   the subtrees under his root node
  80. *
  81. * The avlRebalance procedure must be called after a leaf node has been inserted
  82. * or deleted from the tree. It checks that the AVL balancing rules are
  83. * respected, makes local adjustments to the tree if necessary, recalculates
  84. * the height field of the modified nodes, and repeats the process for every
  85. * node up to the root node. This iteration is necessary because the balancing
  86. * rules for a given node might have been broken by the modification we did on
  87. * one of the subtrees under it.
  88. *
  89. * Because we need to iterate the process up to the root node, and the tree
  90. * nodes does not contain pointers to their father node, we ask the caller of
  91. * this procedure to keep a list of all the nodes traversed from the root node
  92. * to the node just before the recently inserted or deleted node. This is the
  93. * <ancestors> argument. Because each subtree might have to be re-rooted in the
  94. * balancing operation, <ancestors> is actually a list pointers to the node
  95. * pointers - thus if re-rooting occurs, the node pointers can be modified so
  96. * that they keep pointing to the root of a given subtree.
  97. *
  98. * <count> is simply a count of elements in the <ancestors> list.
  99. *
  100. * RETURNS: N/A
  101. */
  102. void avlRebalance
  103.     (
  104.     AVL_NODE ***    ancestors,  /* list of pointers to the ancestor
  105.                        node pointers */
  106.     int         count       /* number ancestors to rebalance */
  107.     )
  108.     {
  109.     while (count > 0)
  110.     {
  111.     AVL_NODE ** nodepp; /* address of the pointer to the root node of
  112.                    the current subtree */
  113.     AVL_NODE *  nodep;  /* points to root node of current subtree */
  114.     AVL_NODE *  leftp;  /* points to root node of left subtree */
  115.     int     lefth;  /* height of the left subtree */
  116.     AVL_NODE *  rightp; /* points to root node of right subtree */
  117.     int     righth; /* height of the right subtree */
  118.     /* 
  119.      * Find the current root node and its two subtrees. By construction,
  120.      * we know that both of them conform to the AVL balancing rules.
  121.      */
  122.     nodepp = ancestors[--count];
  123.     nodep = *nodepp;
  124.     leftp = nodep->left;
  125.     lefth = (leftp != NULL) ? leftp->height : 0;
  126.     rightp = nodep->right;
  127.     righth = (rightp != NULL) ? rightp->height : 0;
  128.     if (righth - lefth < -1)
  129.         {
  130.         /*
  131.          *         *
  132.          *       /   
  133.          *    n+2      n
  134.          *
  135.          * The current subtree violates the balancing rules by beeing too
  136.          * high on the left side. We must use one of two different
  137.          * rebalancing methods depending on the configuration of the left
  138.          * subtree.
  139.          *
  140.          * Note that leftp cannot be NULL or we would not pass there !
  141.          */
  142.         AVL_NODE *  leftleftp;  /* points to root of left left
  143.                        subtree */
  144.         AVL_NODE *  leftrightp; /* points to root of left right
  145.                        subtree */
  146.         int     leftrighth; /* height of left right subtree */
  147.         leftleftp = leftp->left;
  148.         leftrightp = leftp->right;
  149.         leftrighth = (leftrightp != NULL) ? leftrightp->height : 0;
  150.         if ((leftleftp != NULL) && (leftleftp->height >= leftrighth))
  151.         {
  152.         /*
  153.          *            <D>                     <B>
  154.          *             *                    n+2|n+3
  155.          *           /                      /   
  156.          *        <B>     <E>    ---->    <A>     <D>
  157.          *        n+2      n              n+1   n+1|n+2
  158.          *       /                              /   
  159.          *    <A>     <C>                     <C>     <E>
  160.          *    n+1    n|n+1                   n|n+1     n
  161.          */
  162.         nodep->left = leftrightp;   /* D.left = C */
  163.         nodep->height = leftrighth + 1;
  164.         leftp->right = nodep;       /* B.right = D */
  165.         leftp->height = leftrighth + 2;
  166.         *nodepp = leftp;        /* B becomes root */
  167.         }
  168.         else
  169.         {
  170.         /*
  171.          *           <F>
  172.          *            *
  173.          *          /                           <D>
  174.          *       <B>     <G>                     n+2
  175.          *       n+2      n                     /   
  176.          *      /              ---->        <B>     <F>
  177.          *   <A>     <D>                     n+1     n+1
  178.          *    n      n+1                    /       /  
  179.          *          /                   <A>   <C> <E>   <G>
  180.          *       <C>     <E>              n  n|n-1 n|n-1  n
  181.          *      n|n-1   n|n-1
  182.          *
  183.          * We can assume that leftrightp is not NULL because we expect
  184.          * leftp and rightp to conform to the AVL balancing rules.
  185.          * Note that if this assumption is wrong, the algorithm will
  186.          * crash here.
  187.          */
  188.         leftp->right = leftrightp->left;    /* B.right = C */
  189.         leftp->height = leftrighth;
  190.         nodep->left = leftrightp->right;    /* F.left = E */
  191.         nodep->height = leftrighth;
  192.         leftrightp->left = leftp;       /* D.left = B */
  193.         leftrightp->right = nodep;      /* D.right = F */
  194.         leftrightp->height = leftrighth + 1;
  195.         *nodepp = leftrightp;           /* D becomes root */
  196.         }
  197.         }
  198.     else if (righth - lefth > 1)
  199.         {
  200.         /*
  201.          *        *
  202.          *      /   
  203.          *    n      n+2
  204.          *
  205.          * The current subtree violates the balancing rules by beeing too
  206.          * high on the right side. This is exactly symmetric to the
  207.          * previous case. We must use one of two different rebalancing
  208.          * methods depending on the configuration of the right subtree.
  209.          *
  210.          * Note that rightp cannot be NULL or we would not pass there !
  211.          */
  212.         AVL_NODE *  rightleftp; /* points to the root of right left
  213.                        subtree */
  214.         int     rightlefth; /* height of right left subtree */
  215.         AVL_NODE *  rightrightp;    /* points to the root of right right
  216.                        subtree */
  217.         rightleftp = rightp->left;
  218.         rightlefth = (rightleftp != NULL) ? rightleftp->height : 0;
  219.         rightrightp = rightp->right;
  220.         if ((rightrightp != NULL) && (rightrightp->height >= rightlefth))
  221.         {
  222.         /*        <B>                             <D>
  223.          *         *                            n+2|n+3
  224.          *       /                              /   
  225.          *    <A>     <D>        ---->        <B>     <E>
  226.          *     n      n+2                   n+1|n+2   n+1
  227.          *           /                      /   
  228.          *        <C>     <E>             <A>     <C>
  229.          *       n|n+1    n+1              n     n|n+1
  230.          */
  231.         nodep->right = rightleftp;  /* B.right = C */
  232.         nodep->height = rightlefth + 1;
  233.         rightp->left = nodep;       /* D.left = B */
  234.         rightp->height = rightlefth + 2;
  235.         *nodepp = rightp;       /* D becomes root */
  236.         }
  237.         else
  238.         {
  239.         /*        <B>
  240.          *         *
  241.          *       /                               <D>
  242.          *    <A>     <F>                         n+2
  243.          *     n      n+2                        /   
  244.          *           /          ---->        <B>     <F>
  245.          *        <D>     <G>                 n+1     n+1
  246.          *        n+1      n                 /       /  
  247.          *       /                       <A>   <C> <E>   <G>
  248.          *    <C>     <E>                  n  n|n-1 n|n-1  n
  249.          *   n|n-1   n|n-1
  250.          *
  251.          * We can assume that rightleftp is not NULL because we expect
  252.          * leftp and rightp to conform to the AVL balancing rules.
  253.          * Note that if this assumption is wrong, the algorithm will
  254.          * crash here.
  255.          */
  256.         nodep->right = rightleftp->left;    /* B.right = C */
  257.         nodep->height = rightlefth;
  258.         rightp->left = rightleftp->right;   /* F.left = E */
  259.         rightp->height = rightlefth;
  260.         rightleftp->left = nodep;       /* D.left = B */
  261.         rightleftp->right = rightp;     /* D.right = F */
  262.         rightleftp->height = rightlefth + 1;
  263.         *nodepp = rightleftp;           /* D becomes root */
  264.         }
  265.         }
  266.     else
  267.         {
  268.         /*
  269.          * No rebalancing, just set the tree height
  270.          *
  271.          * If the height of the current subtree has not changed, we can
  272.          * stop here because we know that we have not broken the AVL
  273.          * balancing rules for our ancestors.
  274.          */
  275.         int height;
  276.         height = ((righth > lefth) ? righth : lefth) + 1;
  277.         if (nodep->height == height)
  278.         break;
  279.         nodep->height = height;
  280.         }
  281.     }
  282.     }
  283. /*******************************************************************************
  284. *
  285. * avlSearch - search a node in an AVL tree
  286. *
  287. * At the time of the call, <root> is the root node pointer. <key> is the value
  288. * we want to search, and <compare> is the user-provided comparison function.
  289. *
  290. * Note that we cannot have several nodes with the equal keys in the tree, so
  291. * there is no ambiguity about which node will be found.
  292. *
  293. * Also note that the search procedure does not depend on the tree balancing
  294. * rules, but because the tree is balanced, we know that the search procedure
  295. * will always be efficient.
  296. *
  297. * RETURNS: pointer to the node whose key equals <key>, or NULL if there is
  298. * no such node in the tree
  299. */
  300. void * avlSearch
  301.     (
  302.     AVL_TREE        root,           /* root node pointer */
  303.     GENERIC_ARGUMENT    key,            /* search key */
  304.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  305.     )
  306.     {
  307.     AVL_NODE *  nodep;  /* pointer to the current node */
  308.     nodep = root;
  309.     while (1)
  310.     {
  311.     int delta;  /* result of the comparison operation */
  312.     if (nodep == NULL)
  313.         return NULL;    /* not found ! */
  314.     delta = compare (nodep, key);
  315.     if (0 == delta)
  316.         return nodep;   /* found the node */
  317.     else if (delta < 0)
  318.         nodep = nodep->left;
  319.     else
  320.         nodep = nodep->right;
  321.     }
  322.     }
  323. /*******************************************************************************
  324. *
  325. * avlSearchUnsigned - search a node in an AVL tree
  326. *
  327. * This is a specialized implementation of avlSearch for cases where the
  328. * node to be searched is an AVL_UNSIGNED_NODE.
  329. *
  330. * RETURNS: pointer to the node whose key equals <key>, or NULL if there is
  331. * no such node in the tree
  332. */
  333. void * avlSearchUnsigned
  334.     (
  335.     AVL_TREE    root,   /* root node pointer */
  336.     UINT    key /* search key */
  337.     )
  338.     {
  339.     AVL_UNSIGNED_NODE * nodep;  /* pointer to the current node */
  340.     nodep = (AVL_UNSIGNED_NODE *) root;
  341.     while (1)
  342.     {
  343.     if (nodep == NULL)
  344.         return NULL;    /* not found ! */
  345.     if (key == nodep->key)
  346.         return nodep;   /* found the node */
  347.     else if (key < nodep->key)
  348.         nodep = nodep->avl.left;
  349.     else
  350.         nodep = nodep->avl.right;
  351.     }
  352.     }
  353. /*******************************************************************************
  354. *
  355. * avlInsert - insert a node in an AVL tree
  356. *
  357. * At the time of the call, <root> points to the root node pointer. This root
  358. * node pointer is possibly NULL if the tree is empty. <newNode> points to the
  359. * node we want to insert. His left, right and height fields need not be filled,
  360. * but the user will probably have added his own data fields after those. <key>
  361. * is newNode's key, that will be passed to the comparison function. This is
  362. * redundant because it could really be derived from newNode, but the way to do
  363. * this depends on the precise type of newNode so we cannot do this in a generic
  364. * routine. <compare> is the user-provided comparison function.
  365. *
  366. * Note that we cannot have several nodes with the equal keys in the tree, so
  367. * the insertion operation will fail if we try to insert a node that has a
  368. * duplicate key.
  369. *
  370. * Also note that because we keep the tree balanced, the root node pointer that
  371. * is pointed by the <root> argument can be modified in this function.
  372. *
  373. * INTERNAL
  374. * The insertion routine works just like in a non-balanced binary tree : we
  375. * walk down the tree like if we were searching a node, and when we reach a leaf
  376. * node we insert newNode at this position.
  377. *
  378. * Because the balancing procedure needs to be able to walk back to the root
  379. * node, we keep a list of pointers to the pointers we followed on our way down
  380. * the tree.
  381. *
  382. * RETURNS: OK, or ERROR if the tree already contained a node with the same key
  383. */
  384. STATUS avlInsert
  385.     (
  386.     AVL_TREE *      root,       /* pointer to the root node ptr */
  387.     void *      newNode,    /* ptr to the node we want to insert */
  388.     GENERIC_ARGUMENT    key,        /* search key of newNode */
  389.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  390.     )
  391.     {
  392.     AVL_NODE ** nodepp;             /* ptr to current node ptr */
  393.     AVL_NODE ** ancestor[AVL_MAX_HEIGHT];   /* list of pointers to all
  394.                            our ancestor node ptrs */
  395.     int     ancestorCount;          /* number of ancestors */
  396.     nodepp = root;
  397.     ancestorCount = 0;
  398.     while (1)
  399.     {
  400.     AVL_NODE *  nodep;  /* pointer to the current node */
  401.     int     delta;  /* result of the comparison operation */
  402.     nodep = *nodepp;
  403.     if (nodep == NULL)
  404.         break;  /* we can insert a leaf node here ! */
  405.     ancestor[ancestorCount++] = nodepp;
  406.     delta = compare (nodep, key);
  407.     if (0 == delta)
  408.         return ERROR;
  409.     else if (delta < 0)
  410.         nodepp = (AVL_NODE **)&(nodep->left);
  411.     else
  412.         nodepp = (AVL_NODE **)&(nodep->right);
  413.     }
  414.     ((AVL_NODE *)newNode)->left = NULL;
  415.     ((AVL_NODE *)newNode)->right = NULL;
  416.     ((AVL_NODE *)newNode)->height = 1;
  417.     *nodepp = newNode;
  418.     avlRebalance (ancestor, ancestorCount);
  419.     return OK;
  420.     }
  421. /*******************************************************************************
  422. *
  423. * avlInsertUnsigned - insert a node in an AVL tree
  424. *
  425. * This is a specialized implementation of avlInsert for cases where the
  426. * node to be inserted is an AVL_UNSIGNED_NODE.
  427. *
  428. * RETURNS: OK, or ERROR if the tree already contained a node with the same key
  429. */
  430. STATUS avlInsertUnsigned
  431.     (
  432.     AVL_TREE *  root,   /* pointer to the root node ptr */
  433.     void *  newNode /* ptr to the node we want to insert */
  434.     )
  435.     {
  436.     AVL_UNSIGNED_NODE **    nodepp; /* ptr to current node ptr */
  437.     AVL_UNSIGNED_NODE **    ancestor[AVL_MAX_HEIGHT];
  438.             /* list of pointers to all our ancestor node ptrs */
  439.     int     ancestorCount;      /* number of ancestors */
  440.     UINT    key;
  441.     key = ((AVL_UNSIGNED_NODE *)newNode)->key;
  442.     nodepp = (AVL_UNSIGNED_NODE **) root;
  443.     ancestorCount = 0;
  444.     while (1)
  445.     {
  446.     AVL_UNSIGNED_NODE * nodep;  /* pointer to the current node */
  447.     nodep = *nodepp;
  448.     if (nodep == NULL)
  449.         break;  /* we can insert a leaf node here ! */
  450.     ancestor[ancestorCount++] = nodepp;
  451.     if (key == nodep->key)
  452.         return ERROR;
  453.     else if (key < nodep->key)
  454.         nodepp = (AVL_UNSIGNED_NODE **)&(nodep->avl.left);
  455.     else
  456.         nodepp = (AVL_UNSIGNED_NODE **)&(nodep->avl.right);
  457.     }
  458.     ((AVL_NODE *)newNode)->left = NULL;
  459.     ((AVL_NODE *)newNode)->right = NULL;
  460.     ((AVL_NODE *)newNode)->height = 1;
  461.     *nodepp = newNode;
  462.     avlRebalance ((AVL_NODE ***)ancestor, ancestorCount);
  463.     return OK;
  464.     }
  465. /*******************************************************************************
  466. *
  467. * avlDelete - delete a node in an AVL tree
  468. *
  469. * At the time of the call, <root> points to the root node pointer and
  470. * <key> is the key of the node we want to delete. <compare> is the
  471. * user-provided comparison function.
  472. *
  473. * The deletion operation will of course fail if the desired node was not
  474. * already in the tree.
  475. *
  476. * Also note that because we keep the tree balanced, the root node pointer that
  477. * is pointed by the <root> argument can be modified in this function.
  478. *
  479. * On exit, the node is removed from the AVL tree but it is not free()'d.
  480. *
  481. * INTERNAL
  482. * The deletion routine works just like in a non-balanced binary tree : we
  483. * walk down the tree like searching the node we have to delete. When we find
  484. * it, if it is not a leaf node, we have to replace it with a leaf node that
  485. * has an adjacent key. Then the rebalancing operation will have to enforce the
  486. * balancing rules by walking up the path from the leaf node that got deleted
  487. * or moved.
  488. *
  489. * Because the balancing procedure needs to be able to walk back to the root
  490. * node, we keep a list of pointers to the pointers we followed on our way down
  491. * the tree.
  492. *
  493. * RETURNS: pointer to the node we deleted, or NULL if the tree does not
  494. * contain any such node
  495. */
  496. void * avlDelete
  497.     (
  498.     AVL_TREE *      root,   /* pointer to the root node pointer */
  499.     GENERIC_ARGUMENT    key,    /* search key of node we want to delete */
  500.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  501.     )
  502.     {
  503.     AVL_NODE ** nodepp;             /* ptr to current node ptr */
  504.     AVL_NODE *  nodep;              /* ptr to the current node */
  505.     AVL_NODE ** ancestor[AVL_MAX_HEIGHT];   /* list of pointers to all our
  506.                            ancestor node pointers */
  507.     int ancestorCount;              /* number of ancestors */
  508.     AVL_NODE *  deletep;            /* ptr to the node we have to
  509.                            delete */
  510.     nodepp = root;
  511.     ancestorCount = 0;
  512.     while (1)
  513.     {
  514.     int delta;      /* result of the comparison operation */
  515.     nodep = *nodepp;
  516.     if (nodep == NULL)
  517.         return NULL;    /* node was not in the tree ! */
  518.     ancestor[ancestorCount++] = nodepp;
  519.     delta = compare (nodep, key);
  520.     if (0 == delta)
  521.         break;      /* we found the node we have to delete */
  522.     else if (delta < 0)
  523.         nodepp = (AVL_NODE **)&(nodep->left);
  524.     else
  525.         nodepp = (AVL_NODE **)&(nodep->right);
  526.     }
  527.     deletep = nodep;
  528.     if (nodep->left == NULL)
  529.     {
  530.     /*
  531.      * There is no node on the left subtree of delNode.
  532.      * Either there is one (and only one, because of the balancing rules)
  533.      * on its right subtree, and it replaces delNode, or it has no child
  534.      * nodes at all and it just gets deleted
  535.      */
  536.     *nodepp = nodep->right;
  537.     /*
  538.      * we know that nodep->right was already balanced so we don't have to
  539.      * check it again
  540.      */
  541.     ancestorCount--;    
  542.     }
  543.     else
  544.     {
  545.     /*
  546.      * We will find the node that is just before delNode in the ordering
  547.      * of the tree and promote it to delNode's position in the tree.
  548.      */
  549.     AVL_NODE ** deletepp;       /* ptr to the ptr to the node
  550.                            we have to delete */
  551.     int     deleteAncestorCount;    /* place where the replacing
  552.                            node will have to be
  553.                            inserted in the ancestor
  554.                            list */
  555.     deleteAncestorCount = ancestorCount;
  556.     deletepp = nodepp;
  557.     deletep = nodep;
  558.     /* search for node just before delNode in the tree ordering */
  559.     nodepp = (AVL_NODE **)&(nodep->left);
  560.     while (1)
  561.         {
  562.         nodep = *nodepp;
  563.         if (nodep->right == NULL)
  564.         break;
  565.         ancestor[ancestorCount++] = nodepp;
  566.         nodepp = (AVL_NODE **)&(nodep->right);
  567.         }
  568.     /*
  569.      * this node gets replaced by its (unique, because of balancing rules)
  570.      * left child, or deleted if it has no childs at all
  571.      */
  572.     *nodepp = nodep->left;
  573.     /* now this node replaces delNode in the tree */
  574.     nodep->left = deletep->left;
  575.     nodep->right = deletep->right;
  576.     nodep->height = deletep->height;
  577.     *deletepp = nodep;
  578.     /*
  579.      * We have replaced delNode with nodep. Thus the pointer to the left
  580.      * subtree of delNode was stored in delNode->left and it is now
  581.      * stored in nodep->left. We have to adjust the ancestor list to
  582.      * reflect this.
  583.      */
  584.     ancestor[deleteAncestorCount] = (AVL_NODE **)&(nodep->left);
  585.     }
  586.     avlRebalance (ancestor, ancestorCount);
  587.     return deletep;
  588.     }
  589. /*******************************************************************************
  590. *
  591. * avlDeleteUnsigned - delete a node in an AVL tree
  592. *
  593. * This is a specialized implementation of avlDelete for cases where the
  594. * node to be deleted is an AVL_UNSIGNED_NODE.
  595. *
  596. * RETURNS: pointer to the node we deleted, or NULL if the tree does not
  597. * contain any such node
  598. */
  599. void * avlDeleteUnsigned
  600.     (
  601.     AVL_TREE *  root,   /* pointer to the root node pointer */
  602.     UINT    key /* search key of node we want to delete */
  603.     )
  604.     {
  605.     AVL_UNSIGNED_NODE **    nodepp;     /* ptr to current node ptr */
  606.     AVL_UNSIGNED_NODE *     nodep;      /* ptr to the current node */
  607.     AVL_UNSIGNED_NODE **    ancestor[AVL_MAX_HEIGHT];
  608.         /* list of pointers to all our ancestor node pointers */
  609.     int             ancestorCount;  /* number of ancestors */
  610.     AVL_UNSIGNED_NODE *     deletep;    /* ptr to the node we have to
  611.                            delete */
  612.     nodepp = (AVL_UNSIGNED_NODE **)root;
  613.     ancestorCount = 0;
  614.     while (1)
  615.     {
  616.     nodep = *nodepp;
  617.     if (nodep == NULL)
  618.         return NULL;    /* node was not in the tree ! */
  619.     ancestor[ancestorCount++] = nodepp;
  620.     if (key == nodep->key)
  621.         break;      /* we found the node we have to delete */
  622.     else if (key < nodep->key)
  623.         nodepp = (AVL_UNSIGNED_NODE **)&(nodep->avl.left);
  624.     else
  625.         nodepp = (AVL_UNSIGNED_NODE **)&(nodep->avl.right);
  626.     }
  627.     deletep = nodep;
  628.     if (nodep->avl.left == NULL)
  629.     {
  630.     /*
  631.      * There is no node on the left subtree of delNode.
  632.      * Either there is one (and only one, because of the balancing rules)
  633.      * on its right subtree, and it replaces delNode, or it has no child
  634.      * nodes at all and it just gets deleted
  635.      */
  636.     *nodepp = nodep->avl.right;
  637.     /*
  638.      * we know that nodep->right was already balanced so we don't have to
  639.      * check it again
  640.      */
  641.     ancestorCount--;    
  642.     }
  643.     else
  644.     {
  645.     /*
  646.      * We will find the node that is just before delNode in the ordering
  647.      * of the tree and promote it to delNode's position in the tree.
  648.      */
  649.     AVL_UNSIGNED_NODE **    deletepp;   /* ptr to the ptr to the node
  650.                            we have to delete */
  651.     int deleteAncestorCount;    /* place where the replacing node will
  652.                        have to be inserted in the ancestor
  653.                        list */
  654.     deleteAncestorCount = ancestorCount;
  655.     deletepp = nodepp;
  656.     deletep = nodep;
  657.     /* search for node just before delNode in the tree ordering */
  658.     nodepp = (AVL_UNSIGNED_NODE **)&(nodep->avl.left);
  659.     while (1)
  660.         {
  661.         nodep = *nodepp;
  662.         if (nodep->avl.right == NULL)
  663.         break;
  664.         ancestor[ancestorCount++] = nodepp;
  665.         nodepp = (AVL_UNSIGNED_NODE **)&(nodep->avl.right);
  666.         }
  667.     /*
  668.      * this node gets replaced by its (unique, because of balancing rules)
  669.      * left child, or deleted if it has no childs at all
  670.      */
  671.     *nodepp = nodep->avl.left;
  672.     /* now this node replaces delNode in the tree */
  673.     nodep->avl.left = deletep->avl.left;
  674.     nodep->avl.right = deletep->avl.right;
  675.     nodep->avl.height = deletep->avl.height;
  676.     *deletepp = nodep;
  677.     /*
  678.      * We have replaced delNode with nodep. Thus the pointer to the left
  679.      * subtree of delNode was stored in delNode->left and it is now
  680.      * stored in nodep->left. We have to adjust the ancestor list to
  681.      * reflect this.
  682.      */
  683.     ancestor[deleteAncestorCount] = (AVL_UNSIGNED_NODE **)&(nodep->avl.left);
  684.     }
  685.     avlRebalance ((AVL_NODE ***)ancestor, ancestorCount);
  686.     return deletep;
  687.     }
  688. /*******************************************************************************
  689. *
  690. * avlSuccessorGet - find node with key successor to input key on an AVL tree
  691. *
  692. * At the time of the call, <root> is the root node pointer. <key> is the value
  693. * we want to search, and <compare> is the user-provided comparison function.
  694. *
  695. * Note that we cannot have several nodes with the equal keys in the tree, so
  696. * there is no ambiguity about which node will be found.
  697. *
  698. * Also note that the search procedure does not depend on the tree balancing
  699. * rules, but because the tree is balanced, we know that the search procedure
  700. * will always be efficient.
  701. *
  702. * RETURNS: pointer to the node whose key is the immediate successor of <key>,
  703. * or NULL if there is no such node in the tree
  704. */
  705. void * avlSuccessorGet
  706.     (
  707.     AVL_TREE        root,           /* root node pointer */
  708.     GENERIC_ARGUMENT    key,            /* search key */
  709.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  710.     )
  711.     {
  712.     AVL_NODE *  nodep;  /* pointer to the current node */
  713.     AVL_NODE *  superiorp;  /* pointer to the current superior*/
  714.     nodep = root;
  715.     superiorp = NULL;
  716.     while (1)
  717.     {
  718.     int delta;  /* result of the comparison operation */
  719.     if (nodep == NULL)
  720.         return superiorp;
  721.     delta = compare (nodep, key);
  722.     if (delta < 0)
  723.         {
  724.         superiorp = nodep; /* update superiorp */
  725.         nodep = nodep->left;
  726.         }
  727.     else
  728.         nodep = nodep->right;
  729.     }
  730.     }
  731. /*******************************************************************************
  732. *
  733. * avlPredecessorGet - find node with key predecessor to input key on an AVL tree
  734. *
  735. * At the time of the call, <root> is the root node pointer. <key> is the value
  736. * we want to search, and <compare> is the user-provided comparison function.
  737. *
  738. * Note that we cannot have several nodes with the equal keys in the tree, so
  739. * there is no ambiguity about which node will be found.
  740. *
  741. * Also note that the search procedure does not depend on the tree balancing
  742. * rules, but because the tree is balanced, we know that the search procedure
  743. * will always be efficient.
  744. *
  745. * RETURNS: pointer to the node whose key is the immediate predecessor of <key>,
  746. * or NULL if there is no such node in the tree
  747. */
  748. void * avlPredecessorGet
  749.     (
  750.     AVL_TREE        root,           /* root node pointer */
  751.     GENERIC_ARGUMENT    key,            /* search key */
  752.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  753.     )
  754.     {
  755.     AVL_NODE *  nodep;  /* pointer to the current node */
  756.     AVL_NODE *  inferiorp;  /* pointer to the current inferior*/
  757.     nodep = root;
  758.     inferiorp = NULL;
  759.     while (1)
  760.     {
  761.     int delta;  /* result of the comparison operation */
  762.     if (nodep == NULL)
  763.         return inferiorp;
  764.     delta = compare (nodep, key);
  765.     if (delta > 0)
  766.         {
  767.         inferiorp = nodep; /* update inferiorp */
  768.         nodep = nodep->right;
  769.         }
  770.     else
  771.         nodep = nodep->left;
  772.     }
  773.     }
  774. /*******************************************************************************
  775. *
  776. * avlMinimumGet - find node with minimum key
  777. *
  778. * At the time of the call, <root> is the root node pointer. <key> is the value
  779. * we want to search, and <compare> is the user-provided comparison function.
  780. *
  781. * RETURNS: pointer to the node with minimum key; NULL if the tree is empty
  782. */
  783. void * avlMinimumGet
  784.     (
  785.     AVL_TREE        root           /* root node pointer */
  786.     )
  787.     {
  788.     if  (NULL == root)
  789.         return NULL;
  790.     while (root->left != NULL)
  791.         {
  792.         root = root->left;
  793.         }
  794.     return root;
  795.     }
  796. /*******************************************************************************
  797. *
  798. * avlMaximumGet - find node with maximum key
  799. *
  800. * At the time of the call, <root> is the root node pointer. <key> is the value
  801. * we want to search, and <compare> is the user-provided comparison function.
  802. *
  803. * RETURNS: pointer to the node with maximum key; NULL if the tree is empty
  804. */
  805. void * avlMaximumGet
  806.     (
  807.     AVL_TREE        root           /* root node pointer */
  808.     )
  809.     {
  810.     if  (NULL == root)
  811.         return NULL;
  812.     while (root->right != NULL)
  813.         {
  814.         root = root->right;
  815.         }
  816.     return root;
  817.     }
  818. /*******************************************************************************
  819. *
  820. * avlInsertInform - insert a node in an AVL tree and report key holder
  821. *
  822. * At the time of the call, <pRoot> points to the root node pointer. This root
  823. * node pointer is possibly NULL if the tree is empty. <pNewNode> points to the
  824. * node we want to insert. His left, right and height fields need not be filled,
  825. * but the user will probably have added his own data fields after those. <key>
  826. * is newNode's key, that will be passed to the comparison function. This is
  827. * redundant because it could really be derived from newNode, but the way to do
  828. * this depends on the precise type of newNode so we cannot do this in a generic
  829. * routine. <compare> is the user-provided comparison function.
  830. *
  831. * Note that we cannot have several nodes with the equal keys in the tree, so
  832. * the insertion operation will fail if we try to insert a node that has a
  833. * duplicate key. However, if the <replace> boolean is set to true then in
  834. * case of conflict we will remove the old node, we will put in its position the
  835. * new one, and we will return the old node pointer in the postion pointed by
  836. * <ppReplacedNode>.
  837. *
  838. * Also note that because we keep the tree balanced, the root node pointer that
  839. * is pointed by the <pRoot> argument can be modified in this function.
  840. *
  841. * INTERNAL
  842. * The insertion routine works just like in a non-balanced binary tree : we
  843. * walk down the tree like if we were searching a node, and when we reach a leaf
  844. * node we insert newNode at this position.
  845. *
  846. * Because the balancing procedure needs to be able to walk back to the root
  847. * node, we keep a list of pointers to the pointers we followed on our way down
  848. * the tree.
  849. *
  850. * RETURNS: OK, or ERROR if the tree already contained a node with the same key
  851. * and replacement was not allowed. In both cases it will place a pointer to
  852. * the key holder in the position pointed by <ppKeyHolder>.
  853. */
  854. STATUS avlInsertInform
  855.     (
  856.     AVL_TREE *          pRoot,              /* ptr to the root node pointer */
  857.     void *              pNewNode,           /* pointer to the candidate node */
  858.     GENERIC_ARGUMENT    key,                /* unique key of new node */
  859.     void **             ppKeyHolder,        /* ptr to final key holder */
  860.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  861.     )
  862.     {
  863.     AVL_NODE ** nodepp;             /* ptr to current node ptr */
  864.     AVL_NODE ** ancestor[AVL_MAX_HEIGHT];   /* list of pointers to all
  865.                            our ancestor node ptrs */
  866.     int     ancestorCount;          /* number of ancestors */
  867.     if  (NULL == ppKeyHolder) 
  868.         {
  869.         printf("invalid input data were passed to avlInsertInformn");
  870.         return ERROR;
  871.         };
  872.     nodepp = pRoot;
  873.     ancestorCount = 0;
  874.     while (1)
  875.     {
  876.     AVL_NODE *  nodep;  /* pointer to the current node */
  877.     int     delta;  /* result of the comparison operation */
  878.     nodep = *nodepp;
  879.     if (nodep == NULL)
  880.         break;  /* we can insert a leaf node here ! */
  881.     ancestor[ancestorCount++] = nodepp;
  882.     delta = compare (nodep, key);
  883.     if  (0 == delta)
  884.         {
  885.         /* we inform the caller of the key holder node and return ERROR */
  886.         *ppKeyHolder = nodep;
  887.         return ERROR;
  888.         }
  889.     else if (delta < 0)
  890.         nodepp = (AVL_NODE **)&(nodep->left);
  891.     else
  892.         nodepp = (AVL_NODE **)&(nodep->right);
  893.     }
  894.     ((AVL_NODE *)pNewNode)->left = NULL;
  895.     ((AVL_NODE *)pNewNode)->right = NULL;
  896.     ((AVL_NODE *)pNewNode)->height = 1;
  897.     *nodepp = pNewNode;
  898.     *ppKeyHolder = pNewNode;
  899.     avlRebalance (ancestor, ancestorCount);
  900.     return OK;
  901.     }
  902. /*******************************************************************************
  903. *
  904. * avlRemoveInsert - forcefully insert a node in an AVL tree
  905. *
  906. * At the time of the call, <pRoot> points to the root node pointer. This root
  907. * node pointer is possibly NULL if the tree is empty. <pNewNode> points to the
  908. * node we want to insert. His left, right and height fields need not be filled,
  909. * but the user will probably have added his own data fields after those. <key>
  910. * is newNode's key, that will be passed to the comparison function. This is
  911. * redundant because it could really be derived from newNode, but the way to do
  912. * this depends on the precise type of newNode so we cannot do this in a generic
  913. * routine. <compare> is the user-provided comparison function.
  914. *
  915. * Note that we cannot have several nodes with the equal keys in the tree, so
  916. * the insertion operation will fail if we try to insert a node that has a
  917. * duplicate key. However, in case of conflict we will remove the old node, we 
  918. * will put in its position the new one, and we will return the old node pointer
  919. *
  920. * Also note that because we keep the tree balanced, the root node pointer that
  921. * is pointed by the <pRoot> argument can be modified in this function.
  922. *
  923. * INTERNAL
  924. * The insertion routine works just like in a non-balanced binary tree : we
  925. * walk down the tree like if we were searching a node, and when we reach a leaf
  926. * node we insert newNode at this position.
  927. *
  928. * Because the balancing procedure needs to be able to walk back to the root
  929. * node, we keep a list of pointers to the pointers we followed on our way down
  930. * the tree.
  931. *
  932. * RETURNS: NULL if insertion was carried out without replacement, or if 
  933. * replacement occured the pointer to the replaced node
  934. *
  935. */
  936. void * avlRemoveInsert
  937.     (
  938.     AVL_TREE *          pRoot,              /* ptr to the root node pointer */
  939.     void *              pNewNode,           /* pointer to the candidate node */
  940.     GENERIC_ARGUMENT    key,                /* unique key of new node */
  941.     int compare (void *, GENERIC_ARGUMENT)  /* comparison function */
  942.     )
  943.     {
  944.     AVL_NODE ** nodepp;             /* ptr to current node ptr */
  945.     AVL_NODE ** ancestor[AVL_MAX_HEIGHT];   /* list of pointers to all
  946.                            our ancestor node ptrs */
  947.     int     ancestorCount;          /* number of ancestors */
  948.     nodepp = pRoot;
  949.     ancestorCount = 0;
  950.     while (1)
  951.     {
  952.     AVL_NODE *  nodep;  /* pointer to the current node */
  953.     int     delta;  /* result of the comparison operation */
  954.     nodep = *nodepp;
  955.     if (nodep == NULL)
  956.         break;  /* we can insert a leaf node here ! */
  957.     ancestor[ancestorCount++] = nodepp;
  958.     delta = compare (nodep, key);
  959.     if  (0 == delta)
  960.         {
  961.         /* we copy the tree data from the old node to the new node */
  962.         ((AVL_NODE *)pNewNode)->left = nodep->left;
  963.         ((AVL_NODE *)pNewNode)->right = nodep->right;
  964.         ((AVL_NODE *)pNewNode)->height = nodep->height;
  965.         /* and we make the new node child of the old node's parent */
  966.         *nodepp = pNewNode;
  967.         /* before we return it we sterilize the old node */
  968.         nodep->left = NULL;
  969.         nodep->right = NULL;
  970.         nodep->height = 1;
  971.         return nodep;
  972.         }
  973.     else if (delta < 0)
  974.         nodepp = (AVL_NODE **)&(nodep->left);
  975.     else
  976.         nodepp = (AVL_NODE **)&(nodep->right);
  977.     }
  978.     ((AVL_NODE *)pNewNode)->left = NULL;
  979.     ((AVL_NODE *)pNewNode)->right = NULL;
  980.     ((AVL_NODE *)pNewNode)->height = 1;
  981.     *nodepp = pNewNode;
  982.     avlRebalance (ancestor, ancestorCount);
  983.     return NULL;
  984.     }
  985. /*******************************************************************************
  986. *
  987. * avlTreeWalk- walk the whole tree and execute a function on each node
  988. *
  989. * At the time of the call, <pRoot> points to the root node pointer.
  990. *
  991. * RETURNS: OK always
  992. *
  993. */
  994. STATUS avlTreeWalk(AVL_TREE * pRoot, void walkExec(AVL_TREE * ppNode))
  995.     {
  996.     if  ((NULL == pRoot) || (NULL == *pRoot))
  997.         {
  998.         return OK;
  999.         };
  1000.     if  (!(NULL == (*pRoot)->left))
  1001.         {
  1002.         avlTreeWalk((AVL_TREE *)(&((*pRoot)->left)), walkExec);
  1003.         }
  1004.     if  (!(NULL == (*pRoot)->right))
  1005.         {
  1006.         avlTreeWalk((AVL_TREE *)(&((*pRoot)->right)), walkExec);
  1007.         }
  1008.     walkExec(pRoot);
  1009.     return OK;
  1010. }
  1011. /*******************************************************************************
  1012. *
  1013. * avlTreePrint- print the whole tree
  1014. *
  1015. * At the time of the call, <pRoot> points to the root node pointer.
  1016. *
  1017. * RETURNS: OK always
  1018. *
  1019. */
  1020. STATUS avlTreePrint(AVL_TREE * pRoot, void printNode(void * nodep))
  1021.     {
  1022.     if  ((NULL == pRoot) || (NULL == *pRoot))
  1023.         {
  1024.         return OK;
  1025.         };
  1026.     printNode(*pRoot);
  1027.     if  (!(NULL == (*pRoot)->left))
  1028.         {
  1029.         avlTreePrint((AVL_TREE *)(&((*pRoot)->left)), printNode);
  1030.         }
  1031.     if  (!(NULL == (*pRoot)->right))
  1032.         {
  1033.         avlTreePrint((AVL_TREE *)(&((*pRoot)->right)), printNode);
  1034.         }
  1035.     return OK;
  1036. }
  1037. /*******************************************************************************
  1038. *
  1039. * avlTreeErase - erase the whole tree
  1040. *
  1041. * At the time of the call, <pRoot> points to the root node pointer.
  1042. * Unlike the avlDelete routine here we do perform memory management
  1043. * ASSUMING that all nodes carry shallow data only. Otherwise we should
  1044. * use avlTreeWalk with the appropriate walkExec memory freeing function.
  1045. * Since we do not plan to reuse the tree intermediate rebalancing is not needed.
  1046. *
  1047. * RETURNS: OK always
  1048. *
  1049. */
  1050. STATUS avlTreeErase(AVL_TREE * pRoot)
  1051.     {
  1052.     if  ((NULL == pRoot) || (NULL == *pRoot))
  1053.         {
  1054.         return OK;
  1055.         };
  1056.     if  (!(NULL == (*pRoot)->left))
  1057.         {
  1058.         avlTreeErase((AVL_TREE *)(&((*pRoot)->left)));
  1059.         free((*pRoot)->left);
  1060.         (*pRoot)->left = NULL;
  1061.         }
  1062.     if  (!(NULL == (*pRoot)->right))
  1063.         {
  1064.         avlTreeErase((AVL_TREE *)(&((*pRoot)->right)));
  1065.         free((*pRoot)->right);
  1066.         (*pRoot)->right = NULL;
  1067.         }
  1068.     free(*pRoot);
  1069.     *pRoot = NULL;
  1070.     return OK;
  1071. }
  1072. /*******************************************************************************
  1073. *
  1074. * avlTreePrintErase - erase the whole tree assuming that all nodes were
  1075. * created using malloc.
  1076. *
  1077. * At the time of the call, <pRoot> points to the root node pointer.
  1078. * Unlike the avlDelete routine here we do perform memory management.
  1079. * Since we do not plan to reuse the tree intermediate rebalancing is not needed.
  1080. *
  1081. * RETURNS: OK always and assigns NULL to *pRoot.
  1082. *
  1083. */
  1084. STATUS avlTreePrintErase(AVL_TREE * pRoot, void printNode(void * nodep))
  1085.     {
  1086.     if  ((NULL == pRoot) || (NULL == *pRoot))
  1087.         {
  1088.         return OK;
  1089.         };
  1090.     printNode(*pRoot);
  1091.     if  (!(NULL == (*pRoot)->left))
  1092.         {
  1093.         avlTreePrintErase((AVL_TREE *)(&((*pRoot)->left)), printNode);
  1094.         free((*pRoot)->left);
  1095.         (*pRoot)->left = NULL;
  1096.         }
  1097.     if  (!(NULL == (*pRoot)->right))
  1098.         {
  1099.         avlTreePrintErase((AVL_TREE *)(&((*pRoot)->right)), printNode);
  1100.         free((*pRoot)->right);
  1101.         (*pRoot)->right = NULL;
  1102.         }
  1103.     free(*pRoot);
  1104.     *pRoot = NULL;
  1105.     return OK;
  1106. }