eg_bbtree.c

Go to the documentation of this file.
00001 /* EGlib "Efficient General Library" provides some basic structures and
00002  * algorithms commons in many optimization algorithms.
00003  *
00004  * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
00005  * 
00006  * This library is free software; you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation; either version 2.1 of the License, or (at your
00009  * option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful, but 
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
00013  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
00014  * License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this library; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00019  * */
00020 #include "eg_bbtree.h"
00021 /** @file
00022  * @ingroup EGbbtree */
00023 /** @{ */
00024 /* ========================================================================= */
00025 
00026 /* ========================================================================= */
00027 /** @brief Defeault constructor.
00028  * @param mem EGmemPool_t* pointer to the memory pool from where we will
00029  * alocate all memory for internal structures.
00030  * @param compare EGcompare_f pointer to a comparison function, used to mantain
00031  * the tree structure.
00032  * @return EGbbtree_t pointer to an initialized bbtree.
00033  * @par Description:
00034  * Given a memory pool, and a comparison function, we create an empty (and
00035  * initialized) bbtree that works on elements comparable by the given function.
00036  * */
00037 EGbbtree_t *EGnewBbtree (EGmemPool_t * mem,
00038                          EGcompare_f compare)
00039 {
00040   EGbbtree_t *tree = EGmemPoolSMalloc (mem, EGbbtree_t, 1U);
00041   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00042   memset (tree, 0, sizeof (EGbbtree_t));
00043   tree->compare = compare;
00044   tree->mem = mem;
00045   MESSAGE (EG_BBTREE_DEBUGL, "done");
00046   return tree;
00047 }
00048 
00049 /* ========================================================================= */
00050 /** @brief Defeault destructor.
00051  * @param tree EGbbtree_t pointer to the tree to be freed.
00052  * @par Description:
00053  * Given an initialized bbtree, this function free al internal data to the
00054  * local memory pool, but won't free the satelite data.
00055  * */
00056 void EGfreeBbtree (void *tree)
00057 {
00058   /* local variables */
00059   EGbbtreeNode_t *c_node;
00060   unsigned int stack_size = 4 * (1.5 + log2l ((long
00061                                                double) ((EGbbtree_t *) tree)->
00062                                               size + 1)),
00063     stack_pos = 0;
00064   EGbbtreeNode_t **stack = EGmemPoolSMalloc (((EGbbtree_t *) tree)->mem,
00065                                              EGbbtreeNode_t *, stack_size);
00066 
00067   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00068   /* init the stack */
00069   stack[stack_pos] = ((EGbbtree_t *) tree)->root;
00070   if (((EGbbtree_t *) tree)->size)
00071     while (~stack_pos)
00072     {
00073       c_node = stack[stack_pos];
00074       stack_pos--;
00075       if (c_node->left)
00076         stack[++stack_pos] = c_node->left;
00077       if (c_node->right)
00078         stack[++stack_pos] = c_node->right;
00079       EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, ((EGbbtree_t *) tree)->mem);
00080     }
00081   ((EGbbtree_t *) tree)->size = 0;
00082 
00083   /* ending */
00084   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size,
00085                   ((EGbbtree_t *) tree)->mem);
00086   EGmemPoolSFree (tree, EGbbtree_t, 1, ((EGbbtree_t *) tree)->mem);
00087   MESSAGE (EG_BBTREE_DEBUGL, "done");
00088   return;
00089 }
00090 
00091 /* ========================================================================= */
00092 /** @brief Given an initialized bbtree, left it at it initial state (just after
00093  * EGnewBbtree).
00094  * @param tree EGbbtree_t* pointer to the tree to be reseted to its initial
00095  * state.
00096  * @param dataFree free function for the satelite data.
00097  * @return zero on success, non-zero otherwise.
00098  * @par Description:
00099  * Set the structure to its initiial state, free all internal data to the
00100  * memory pool, and apply the given free function to the satelite data.
00101  * */
00102 int EGbbtreeClear (EGbbtree_t * tree,
00103                    EGfree_f dataFree)
00104 {
00105   /* local variables */
00106   EGbbtreeNode_t *c_node;
00107   unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00108     stack_pos = 0;
00109   EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00110                                              EGbbtreeNode_t *, stack_size);
00111 
00112   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00113   /* init the stack */
00114   stack[stack_pos] = tree->root;
00115   if (tree->size)
00116     while (~stack_pos)
00117     {
00118       c_node = stack[stack_pos];
00119       stack_pos--;
00120       if (c_node->left)
00121         stack[++stack_pos] = c_node->left;
00122       if (c_node->right)
00123         stack[++stack_pos] = c_node->right;
00124       if (dataFree)
00125         dataFree (c_node->this);
00126       EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, tree->mem);
00127     }
00128   tree->size = 0;
00129   tree->root = 0;
00130 
00131   /* ending */
00132   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size, tree->mem);
00133   MESSAGE (EG_BBTREE_DEBUGL, "done");
00134   return 0;
00135 }
00136 
00137 /* ========================================================================= */
00138 /** @brief Given an initialized bbtree, left it at it initial state (just after
00139  * EGnewBbtree).
00140  * @param tree EGbbtree_t* pointer to the tree to be reseted to its initial
00141  * state.
00142  * @param dataFree free function for the satelite data.
00143  * @param datamem pointer to the memory pool used to allocate the satelite
00144  * data.
00145  * @return zero on success, non-zero otherwise.
00146  * @par Description:
00147  * Set the structure to its initiial state, free all internal data to the
00148  * memory pool, and apply the given free function to the satelite data.
00149  * */
00150 int EGbbtreeClearMP (EGbbtree_t * tree,
00151                      EGfreeMP_f dataFree,
00152                      EGmemPool_t * datamem)
00153 {
00154   /* local variables */
00155   EGbbtreeNode_t *c_node;
00156   unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00157     stack_pos = 0;
00158   EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00159                                              EGbbtreeNode_t *, stack_size);
00160 
00161   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00162   /* init the stack */
00163   stack[stack_pos] = tree->root;
00164   if (tree->size)
00165     while (~stack_pos)
00166     {
00167       c_node = stack[stack_pos];
00168       stack_pos--;
00169       if (c_node->left)
00170         stack[++stack_pos] = c_node->left;
00171       if (c_node->right)
00172         stack[++stack_pos] = c_node->right;
00173       if (dataFree)
00174         dataFree (c_node->this, datamem);
00175       EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, tree->mem);
00176     }
00177   tree->size = 0;
00178   tree->root = 0;
00179 
00180   /* ending */
00181   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size, tree->mem);
00182   MESSAGE (EG_BBTREE_DEBUGL, "done");
00183   return 0;
00184 }
00185 
00186 /* ========================================================================= */
00187 /** @brief Find an element in the tree.
00188  * @param tree EGbbtree_t* pointer to the tree where we will perform the
00189  * search.
00190  * @param elem void* pointer to the structure that we are looking for.
00191  * @return EGbbtreeNode_t pointer to the node in the tree containing the
00192  * element, if no such node exists, return NULL.
00193  * @par Description:
00194  * This function will searxh for the element in the tree that satisfy
00195  * compare(elem,found)==0. */
00196 EGbbtreeNode_t *EGbbtreeFind (EGbbtree_t * tree,
00197                               const void *elem)
00198 {
00199   /* local variables */
00200   EGbbtreeNode_t *c_node = tree->root;
00201   int rval = 0;
00202 
00203   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00204   /* now we iterate */
00205   while (c_node)
00206   {
00207     rval = tree->compare (elem, c_node->this);
00208     if (!rval)
00209       break;
00210     if (rval < 0)
00211       c_node = c_node->left;
00212     else
00213       c_node = c_node->right;
00214   }
00215 
00216   /* ending */
00217   MESSAGE (EG_BBTREE_DEBUGL, "done");
00218   return c_node;
00219 }
00220 
00221 /* ========================================================================= */
00222 /** @brief Macro to access the depth of the left child of a nodo */
00223 #define EGbbtreeLeftDepth(__node) ((__node)->left?(__node)->left->depth:0U)
00224 
00225 /* ========================================================================= */
00226 /** @brief Macro to access the depth of the right child of a nodo */
00227 #define EGbbtreeRightDepth(__node) ((__node)->right?(__node)->right->depth:0U)
00228 
00229 /* ========================================================================= */
00230 /** @brief Update the depth of a node, this function assumes that the depth of
00231  * the sons of the node are correctly set-up */
00232 static inline int EGbbtreeUpdateDepth (EGbbtreeNode_t * const p_node)
00233 {
00234   p_node->depth = EGbbtreeLeftDepth (p_node);
00235   if (p_node->right && p_node->depth < p_node->right->depth)
00236     p_node->depth = p_node->right->depth;
00237   p_node->depth++;
00238   return 0;
00239 }
00240 
00241 /* ========================================================================= */
00242 /** @brief Rotate the given node to the right, and update the correspondig
00243  * depths.
00244  * @param p_node EGbbtreeNode_t** pointer to the pointer of the tree to rotate.
00245  * @param tree EGbbtree_t* pointer to the tree where the rotation is being
00246  * performed.
00247  * @return zero on success, non-zero otherwise. */
00248 static inline int EGbbtreeRotateRight (EGbbtree_t * tree,
00249                                        EGbbtreeNode_t ** p_node)
00250 {
00251   /* local variables */
00252   EGbbtreeNode_t *c_node = (*p_node)->left;
00253   MESSAGE (EG_BBTREE_DEBUGL, "entering at node %p", (void *) (*p_node));
00254   /* note that only c_node->right change relative positions, and *p_node, and
00255    * their parents. */
00256   if (!(c_node->parent = (*p_node)->parent))
00257     tree->root = c_node;
00258   else
00259   {
00260     if ((*p_node)->parent->left == (*p_node))
00261       (*p_node)->parent->left = c_node;
00262     else
00263       (*p_node)->parent->right = c_node;
00264   }
00265   if (((*p_node)->left = c_node->right))
00266     (*p_node)->left->parent = (*p_node);
00267   c_node->right = (*p_node);
00268   (*p_node)->parent = c_node;
00269   /* now we recalculate the depth of *p_node */
00270   EGbbtreeUpdateDepth (*p_node);
00271   /* update *p_node to c_node, i.e. to the root of the sub-tree */
00272   (*p_node) = c_node;
00273   /* now we recalculate the depth of *p_node */
00274   EGbbtreeUpdateDepth (*p_node);
00275   MESSAGE (EG_BBTREE_DEBUGL, "done");
00276   return 0;
00277 }
00278 
00279 /* ========================================================================= */
00280 /** @brief Rotate the given node to the left, and update the correspondig
00281  * depths.
00282  * @param p_node EGbbtreeNode_t** pointer to the pointer of the tree to rotate.
00283  * @param tree EGbbtree_t* pointer to the tree where the rotation is being
00284  * performed.
00285  * @return zero on success, non-zero otherwise. */
00286 static inline int EGbbtreeRotateLeft (EGbbtree_t * tree,
00287                                       EGbbtreeNode_t ** p_node)
00288 {
00289   /* local variables */
00290   EGbbtreeNode_t *c_node = (*p_node)->right;
00291   MESSAGE (EG_BBTREE_DEBUGL, "entering at node %p", (void *) (*p_node));
00292   /* note that only c_node->left change relative positions, and *p_node, and
00293    * their parents. */
00294   if (!(c_node->parent = (*p_node)->parent))
00295     tree->root = c_node;
00296   else
00297   {
00298     if ((*p_node)->parent->left == (*p_node))
00299       (*p_node)->parent->left = c_node;
00300     else
00301       (*p_node)->parent->right = c_node;
00302   }
00303   if (((*p_node)->right = c_node->left))
00304     (*p_node)->right->parent = (*p_node);
00305   c_node->left = (*p_node);
00306   (*p_node)->parent = c_node;
00307   /* now we recalculate the depth of *p_node */
00308   EGbbtreeUpdateDepth (*p_node);
00309   /* update *p_node to c_node, i.e. to the root of the sub-tree */
00310   (*p_node) = c_node;
00311   /* now we recalculate the depth of *p_node */
00312   EGbbtreeUpdateDepth (*p_node);
00313   MESSAGE (EG_BBTREE_DEBUGL, "done");
00314   return 0;
00315 }
00316 
00317 /* ========================================================================= */
00318 /** @brief This function balances a tree by rotations, starting in the given
00319  * node and working upwards.
00320  * @param p_node EGbbtreeNode_t** pointer to the pointer of the tree to rotate.
00321  * @param tree EGbbtree_t* pointer to the tree where the rotation is being
00322  * performed.
00323  * @return zero on success, non-zero otherwise.
00324  * */
00325 static inline int EGbbtreeBalance (EGbbtree_t * tree,
00326                                    EGbbtreeNode_t ** p_node)
00327 {
00328   /* local variables */
00329   unsigned diff;
00330   int rval = 0;
00331   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00332 
00333   /* mian loop */
00334   while (*p_node)
00335   {
00336     /* first we set the depth of p_node */
00337     EGbbtreeUpdateDepth (*p_node);
00338     diff = EGbbtreeLeftDepth (*p_node) - EGbbtreeRightDepth (*p_node);
00339     /* here we test if we have to rotate */
00340     switch (diff)
00341     {
00342       /* case that the left side is deeper */
00343     case 2U:
00344       if (EGbbtreeRightDepth ((*p_node)->left) >
00345           EGbbtreeLeftDepth ((*p_node)->left))
00346       {
00347         (*p_node) = (*p_node)->left;
00348         rval = EGbbtreeRotateLeft (tree, p_node);
00349         CHECKRVAL (rval);
00350         (*p_node) = (*p_node)->parent;
00351       }
00352       rval = EGbbtreeRotateRight (tree, p_node);
00353       CHECKRVAL (rval);
00354       break;
00355       /* case the right side is deeper */
00356     case (-2U):
00357       if (EGbbtreeLeftDepth ((*p_node)->right) >
00358           EGbbtreeRightDepth ((*p_node)->right))
00359       {
00360         (*p_node) = (*p_node)->right;
00361         rval = EGbbtreeRotateRight (tree, p_node);
00362         CHECKRVAL (rval);
00363         (*p_node) = (*p_node)->parent;
00364       }
00365       rval = EGbbtreeRotateLeft (tree, p_node);
00366       CHECKRVAL (rval);
00367       break;
00368       /* if the difference in depth is no more than one, do nothing */
00369     case 1U:
00370     case 0U:
00371     case (-1U):
00372       break;
00373       /* if the difference is non of the above, throw an exception and exit */
00374     default:
00375       rval = 1;
00376       TESTG (1, CLEANUP, "unknown depth difference %u, fix the code!", diff);
00377       break;
00378 
00379     }
00380     MESSAGE (EG_BBTREE_DEBUGL, "  setting pnode(%p) to parent (%p)",
00381              (void *) (*p_node), (void *) ((*p_node)->parent));
00382     (*p_node) = (*p_node)->parent;
00383   }
00384 CLEANUP:
00385   MESSAGE (EG_BBTREE_DEBUGL, "done");
00386   return rval;
00387 }
00388 
00389 /* ========================================================================= */
00390 /** @brief Add a new element to the tree.
00391  * @param tree EGbbtree_t* pointer to the tree where we will add the new
00392  * element.
00393  * @param elem void* pointer to the element to be added to the tree.
00394  * @return EGbbtreeNode_t* pointer to the newly created node containing the
00395  * inserted element, if the eement already existed, we return NULL.
00396  * @par Description:
00397  * Add a new element (according to the comopare function) to the tree and
00398  * maintain the balance on the tree. If the element is repeated on the tree, it
00399  * will return NULL.
00400  * */
00401 EGbbtreeNode_t *EGbbtreeAdd (EGbbtree_t * tree,
00402                              void *elem)
00403 {
00404   /* local variables */
00405   EGbbtreeNode_t *c_node = tree->root,
00406    *p_node = 0;
00407   int rval = 0;
00408   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00409 
00410   /* now we iterate */
00411   while (c_node)
00412   {
00413     rval = tree->compare (elem, c_node->this);
00414     p_node = c_node;
00415     c_node = (rval < 0) ? c_node->left : ((rval > 0) ? c_node->right : 0);
00416   }
00417   /* now p_node is the parent of the node where we will add the element, and
00418    * rval stores the value of compare(elem,p_node->this) if p_node is not NULL
00419    * ,i.e. if we are not addiing at the root of the tree. */
00420   if (p_node)
00421   {
00422     if (rval < 0)
00423       p_node->left = c_node = EGmemPoolSMalloc (tree->mem, EGbbtreeNode_t, 1U);
00424     else
00425       p_node->right = c_node = EGmemPoolSMalloc (tree->mem, EGbbtreeNode_t, 1U);
00426   }
00427   else
00428   {
00429     tree->root = c_node = EGmemPoolSMalloc (tree->mem, EGbbtreeNode_t, 1U);
00430   }
00431   memset (c_node, 0, sizeof (EGbbtreeNode_t));
00432   c_node->this = elem;
00433   c_node->parent = p_node;
00434   c_node->depth = 1;
00435   tree->size++;
00436 
00437   /* now we need to balance the tree */
00438   rval = EGbbtreeBalance (tree, &p_node);
00439   ADVCHECKRVAL (rval, 0);
00440 
00441   /* ending */
00442   MESSAGE (EG_BBTREE_DEBUGL, "done");
00443   return c_node;
00444 }
00445 
00446 /* ========================================================================= */
00447 /** @brief, get the predecessor of the current node.
00448  * @param node EGbbtreeNode_t* pointer to the node to wich we are looking for
00449  * its predecessor.
00450  * @return EGbbtreeNode_t* pointer to the predecessor of the given node.
00451  * @par Description:
00452  * This function try to find the predecessor of the given node, if no such
00453  * node exists, return NULL.
00454  * */
00455 EGbbtreeNode_t *EGbbtreePredecessor (EGbbtreeNode_t * node)
00456 {
00457   /* local variables */
00458   EGbbtreeNode_t *c_node = node->left,
00459    *x_node = node;
00460   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00461   if (c_node)
00462   {
00463     while (c_node->right)
00464       c_node = c_node->right;
00465     MESSAGE (EG_BBTREE_DEBUGL, "done");
00466     return c_node;
00467   }
00468   c_node = node->parent;
00469   while (c_node && x_node == c_node->left)
00470   {
00471     x_node = c_node;
00472     c_node = c_node->parent;
00473   }
00474   MESSAGE (EG_BBTREE_DEBUGL, "done");
00475   return c_node;
00476 }
00477 
00478 /* ========================================================================= */
00479 /** @brief, get the successor of the current node.
00480  * @param node EGbbtreeNode_t* pointer to the node to wich we are looking for
00481  * its successor.
00482  * @return EGbbtreeNode_t* pointer to the successor of the given node.
00483  * @par Description:
00484  * This function try to find the successor of the given node, if no such node
00485  * exists, return NULL.
00486  * */
00487 EGbbtreeNode_t *EGbbtreeSuccessor (EGbbtreeNode_t * node)
00488 {
00489   /* local variables */
00490   EGbbtreeNode_t *c_node = node->right,
00491    *x_node = node;
00492   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00493   if (c_node)
00494   {
00495     while (c_node->left)
00496       c_node = c_node->left;
00497     MESSAGE (EG_BBTREE_DEBUGL, "done");
00498     return c_node;
00499   }
00500   c_node = node->parent;
00501   while (c_node && x_node == c_node->right)
00502   {
00503     x_node = c_node;
00504     c_node = c_node->parent;
00505   }
00506   MESSAGE (EG_BBTREE_DEBUGL, "done");
00507   return c_node;
00508 }
00509 
00510 /* ========================================================================= */
00511 /** @brief Delete an element from the tree.
00512  * @param tree EGbbtree_t* pointer to the tree from where we will eliminate the
00513  * given node.
00514  * @param node EGbbtreeNode_t* pointer to the node of the tree to be
00515  * eliminated.
00516  * @return zero on success, non-zero otherwise.
00517  * @par Description:
00518  * Given an initialized tree, and a ode pertaianing to it (the code won't check
00519  * this), it will eliminate the node form the tree. If an error occour, it will
00520  * return non-zero. Note that this funcion won't free the internal satelite
00521  * data of the given node, this should be done by the caller of the function
00522  * __BEFORE__ using this function.
00523  * */
00524 int EGbbtreeRemove (EGbbtree_t * tree,
00525                     EGbbtreeNode_t * node)
00526 {
00527   /* local variables */
00528   EGbbtreeNode_t *p_node = node->parent;
00529   EGbbtreeNode_t *n_node;
00530   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00531 
00532   /* there are three cases to follow, the dirs is that the current node has
00533    * both left and right childrends, in this case we move it so that it now has
00534    * either a left child or a right child, but no both. */
00535   if (node->left && node->right)
00536   {
00537     n_node = EGbbtreePredecessor (node);
00538     /* we handle in a different manner the case where the predecesor of node is
00539      * its left son */
00540     /* set n_node<->parent connections */
00541     if (n_node->parent == node)
00542     {
00543       if ((n_node->parent = node->parent))
00544       {
00545         if (node->parent->left == node)
00546           node->parent->left = n_node;
00547         else
00548           node->parent->right = n_node;
00549       }
00550       else
00551         tree->root = n_node;
00552       /* set n_node<->right connections */
00553       n_node->right = node->right;
00554       n_node->right->parent = n_node;
00555       p_node = n_node;
00556       EGbbtreeUpdateDepth (n_node);
00557       goto END;
00558     }
00559     /* set n_node->parent and reverse connection */
00560     p_node = n_node->parent;
00561     if ((n_node->parent = node->parent))
00562     {
00563       if (node->parent->left == node)
00564         node->parent->left = n_node;
00565       else
00566         node->parent->right = n_node;
00567     }
00568     else
00569       tree->root = n_node;
00570     /* set node->parent and reverse connection */
00571     EXIT (node == p_node, "node and p_node are equal");
00572     node->parent = p_node;
00573     if (node->parent->left == n_node)
00574       node->parent->left = node;
00575     else
00576       node->parent->right = node;
00577     /* set node->left */
00578     n_node->right = node->left;
00579     if ((node->left = n_node->left))
00580       node->left->parent = node;
00581     /* set n_node->left */
00582     if ((n_node->left = n_node->right))
00583       n_node->left->parent = n_node;
00584     /* set n_node->right */
00585     if ((n_node->right = node->right))
00586       node->right->parent = n_node;
00587     /* set node->right */
00588     node->right = 0;
00589     /* update depths */
00590     EGbbtreeUpdateDepth (n_node);
00591     EGbbtreeUpdateDepth (node);
00592   }
00593 
00594   /* now node has either one or none child */
00595   if (node->right)
00596   {
00597     if (p_node)
00598     {
00599       if (p_node->left == node)
00600         p_node->left = node->right;
00601       else
00602         p_node->right = node->right;
00603       node->right->parent = p_node;
00604     }
00605     else
00606     {
00607       tree->root = node->right;
00608       node->right->parent = 0;
00609     }
00610   }
00611   else if (node->left)
00612   {
00613     if (p_node)
00614     {
00615       if (p_node->left == node)
00616         p_node->left = node->left;
00617       else
00618         p_node->right = node->left;
00619       node->left->parent = p_node;
00620     }
00621     else
00622     {
00623       tree->root = node->left;
00624       node->left->parent = 0;
00625     }
00626   }
00627   /* this is the easiest case, we just eliminate the node, and balance its
00628    * parent. */
00629   else
00630   {
00631     if (p_node)
00632     {
00633       if (p_node->left == node)
00634         p_node->left = 0;
00635       else
00636         p_node->right = 0;
00637     }
00638     else
00639       tree->root = 0;
00640   }
00641 END:
00642   /* this are common steps to follow */
00643   EGmemPoolSFree (node, EGbbtreeNode_t, 1, tree->mem);
00644   tree->size--;
00645   /* and to finish we balance the tree */
00646   MESSAGE (EG_BBTREE_DEBUGL, "done");
00647   return EGbbtreeBalance (tree, &p_node);
00648 }
00649 
00650 /* ========================================================================= */
00651 /** @brief Display function for the tree.
00652  * @param tree EGbbtree_t* pointer to the tree to be displayed.
00653  * @param dataDisplay EGdisplay_f function that display the internal data (can
00654  * be NULL).
00655  * @param file FILE* pointer to the output stream.
00656  * @par Description: Display information of the tree, it's nodes, and the
00657  * internal data.
00658  * */
00659 void EGbbtreeDisplay (EGbbtree_t * tree,
00660                       EGdisplay_f dataDisplay,
00661                       FILE * file)
00662 {
00663   /* local variables */
00664   EGbbtreeNode_t *c_node;
00665   unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00666     stack_pos = 0;
00667   EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00668                                              EGbbtreeNode_t *, stack_size);
00669   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00670 
00671   /* init the stack */
00672   stack[stack_pos] = tree->root;
00673 
00674   /* display the general information first */
00675   fprintf (file, "\nTree %p:\n"
00676            "\tNodes  :  %u\n"
00677            "\tPool   :  %p\n"
00678            "\tCompare:  %tX\n", (void *) tree, tree->size,
00679            (void *) tree->mem, (size_t) (tree->compare));
00680 
00681   if (tree->size)
00682     while (~stack_pos)
00683     {
00684       c_node = stack[stack_pos];
00685       stack_pos--;
00686       if (c_node->left)
00687         stack[++stack_pos] = c_node->left;
00688       if (c_node->right)
00689         stack[++stack_pos] = c_node->right;
00690       fprintf (file, "  Node %p (DP:%d,THS:%p)\n", (void *) c_node,
00691                c_node->depth, c_node->this);
00692       if (dataDisplay)
00693         dataDisplay (c_node->this, file);
00694     }
00695 
00696   /* ending */
00697   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size,
00698                   ((EGbbtree_t *) tree)->mem);
00699   MESSAGE (EG_BBTREE_DEBUGL, "done");
00700   return;
00701 }
00702 
00703 /* ========================================================================= */
00704 /** @brief Return the minimum element in the tree.
00705  * @param tree EGbbtree_t* pointer to the tree to be displayed.
00706  * @return pointer to the treeNode pointing to the minimum element.
00707  * @par Description:
00708  * Given a tree, return the minimum eloement on the tree (pointer to the
00709  * connector).
00710  * */
00711 EGbbtreeNode_t *EGbbtreeMin (EGbbtree_t * tree)
00712 {
00713   EGbbtreeNode_t *root = tree->root;
00714   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00715   while (root && root->left)
00716     root = root->left;
00717   MESSAGE (EG_BBTREE_DEBUGL, "done");
00718   return root;
00719 }
00720 
00721 /* ========================================================================= */
00722 /** @brief Return the maximum element in the tree.
00723  * @param tree EGbbtree_t* pointer to the tree to be displayed.
00724  * @return pointer to the treeNode pointing to the maximum element.
00725  * @par Description:
00726  * Given a tree, return the maximum eloement on the tree (pointer to the
00727  * connector).
00728  * */
00729 EGbbtreeNode_t *EGbbtreeMax (EGbbtree_t * tree)
00730 {
00731   EGbbtreeNode_t *root = tree->root;
00732   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00733   while (root && root->right)
00734     root = root->right;
00735   MESSAGE (EG_BBTREE_DEBUGL, "done");
00736   return root;
00737 }
00738 
00739 
00740 
00741 /* ========================================================================= */
00742 /** } */
00743 /* end of eg_bbtree.c */

Generated on Mon Jan 30 08:48:52 2006 for EGlib by  doxygen 1.4.5