eg_bbtree.h

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 #ifndef __EG_BBTREE_H__
00021 #define __EG_BBTREE_H__
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <limits.h>
00026 #include <float.h>
00027 #include <math.h>
00028 #include "eg_io.h"
00029 #include "eg_config.h"
00030 #include "eg_macros.h"
00031 #include "eg_mempool.h"
00032 #include "eg_compare.h"
00033 /* ========================================================================= */
00034 /** @defgroup EGbbtree EGbbtree
00035  *
00036  * Here we define an implementation of bimary balanced trees. In this
00037  * implementation the depth of the tree is bounded by 2*ceil(log_2(size)).
00038  * Note that this structure don't support repeated elements.
00039  *
00040  * -2005-09-09
00041  *          - Fix EGbbtreeAdd (By Faram Engineer)
00042  *          
00043  * -2005-09-08
00044  *          - Fix EGbbtreeClear (By Faram Engineer)
00045  *
00046  * -2004-08-16
00047  *          - First Implementation
00048  * */
00049 /** @file
00050  * @ingroup EGbbtree */
00051 /** @{ */
00052 /* ========================================================================= */
00053 
00054 /* ========================================================================= */
00055 /** @brief Macro controling the debuging level for this structure. */
00056 #define EG_BBTREE_DEBUGL 10
00057 
00058 /* ========================================================================= */
00059 /** @brief Balance Binary Tree Node structure.
00060  * @par Description:
00061  * This structure stores a pointer to satellite data, the depth of the node,
00062  * and pointers to it parent and sons.
00063  * */
00064 typedef struct EGbbtreeNode_t
00065 {
00066   struct EGbbtreeNode_t *parent;/**< Pointer to the parent of this node. */
00067   struct EGbbtreeNode_t *left;  /**< Pointer to the lefthand son. */
00068   struct EGbbtreeNode_t *right; /**< Pointer to the righthand son. */
00069   void *this;         /**< Pointer to the satelite data */
00070   unsigned depth;     /**< Note that the depth can be stored in a 
00071                         char, but since the size of the struct is anyway the 
00072                         complete word, we won't gain anything by doing this. 
00073                         This field store the longest distance to a leaf of the
00074                         related sub-tree. */
00075 }
00076 EGbbtreeNode_t;
00077 
00078 /* ========================================================================= */
00079 /** @brief Balance Binary Tree structure.
00080  * @par Description:
00081  * This structure has a pointer to a root node, the number of nodes in the tree
00082  * structure, and a pointer to a comparison function used to build the tree and
00083  * to add/remove elements from the tree, and a pointer to a memory manager from
00084  * where the local memory will be draw.
00085  * */
00086 typedef struct EGbbtree_t
00087 {
00088   EGbbtreeNode_t *root; /**< Pointer to the root of the tree. */
00089   EGmemPool_t *mem;     /**< Pointer to the local memory manager from where all
00090                           memory will be draw/freed. */
00091   EGcompare_f compare;  /**< Pointer to a comparison function, this function
00092                           will be used while building/modifying the tree */
00093   unsigned int size;    /**< Number of nodes in the tree. */
00094 }
00095 EGbbtree_t;
00096 
00097 /* ========================================================================= */
00098 /** @brief Defeault constructor.
00099  * @param mem EGmemPool_t* pointer to the memory pool from where we will
00100  * alocate all memory for internal structures.
00101  * @param compare EGcompare_f pointer to a comparison function, used to mantain
00102  * the tree structure.
00103  * @return EGbbtree_t pointer to an initialized bbtree.
00104  * @par Description:
00105  * Given a memory pool, and a comparison function, we create an empty (and
00106  * initialized) bbtree that works on elements comparable by the given function.
00107  * */
00108 extern inline EGbbtree_t *EGnewBbtree (EGmemPool_t * mem,
00109                                        EGcompare_f compare)
00110 {
00111   EGbbtree_t *tree = EGmemPoolSMalloc (mem, EGbbtree_t, 1U);
00112   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00113   memset (tree, 0, sizeof (EGbbtree_t));
00114   tree->compare = compare;
00115   tree->mem = mem;
00116   MESSAGE (EG_BBTREE_DEBUGL, "done");
00117   return tree;
00118 }
00119 
00120 /* ========================================================================= */
00121 /** @brief Defeault destructor.
00122  * @param tree EGbbtree_t pointer to the tree to be freed.
00123  * @par Description:
00124  * Given an initialized bbtree, this function free al internal data to the
00125  * local memory pool, but won't free the satelite data.
00126  * */
00127 extern inline void EGfreeBbtree (void *tree)
00128 {
00129   /* local variables */
00130   EGbbtreeNode_t *c_node;
00131   unsigned int stack_size = 4 * (1.5 + log2l ((long
00132                                                double) ((EGbbtree_t *) tree)->
00133                                               size + 1)),
00134     stack_pos = 0;
00135   EGbbtreeNode_t **stack = EGmemPoolSMalloc (((EGbbtree_t *) tree)->mem,
00136                                              EGbbtreeNode_t *, stack_size);
00137 
00138   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00139   /* init the stack */
00140   stack[stack_pos] = ((EGbbtree_t *) tree)->root;
00141   if (((EGbbtree_t *) tree)->size)
00142     while (~stack_pos)
00143     {
00144       c_node = stack[stack_pos];
00145       stack_pos--;
00146       if (c_node->left)
00147         stack[++stack_pos] = c_node->left;
00148       if (c_node->right)
00149         stack[++stack_pos] = c_node->right;
00150       EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, ((EGbbtree_t *) tree)->mem);
00151     }
00152   ((EGbbtree_t *) tree)->size = 0;
00153 
00154   /* ending */
00155   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size,
00156                   ((EGbbtree_t *) tree)->mem);
00157   EGmemPoolSFree (tree, EGbbtree_t, 1, ((EGbbtree_t *) tree)->mem);
00158   MESSAGE (EG_BBTREE_DEBUGL, "done");
00159   return;
00160 }
00161 
00162 /* ========================================================================= */
00163 /** @brief Given an initialized bbtree, left it at it initial state (just after
00164  * EGnewBbtree).
00165  * @param tree EGbbtree_t* pointer to the tree to be reseted to its initial
00166  * state.
00167  * @param dataFree free function for the satelite data.
00168  * @return zero on success, non-zero otherwise.
00169  * @par Description:
00170  * Set the structure to its initiial state, free all internal data to the
00171  * memory pool, and apply the given free function to the satelite data.
00172  * */
00173 extern inline int EGbbtreeClear (EGbbtree_t * tree,
00174                                  EGfree_f dataFree)
00175 {
00176   /* local variables */
00177   EGbbtreeNode_t *c_node;
00178   unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00179     stack_pos = 0;
00180   EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00181                                              EGbbtreeNode_t *, stack_size);
00182 
00183   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00184   /* init the stack */
00185   stack[stack_pos] = tree->root;
00186   if (tree->size)
00187     while (~stack_pos)
00188     {
00189       c_node = stack[stack_pos];
00190       stack_pos--;
00191       if (c_node->left)
00192         stack[++stack_pos] = c_node->left;
00193       if (c_node->right)
00194         stack[++stack_pos] = c_node->right;
00195       if (dataFree)
00196         dataFree (c_node->this);
00197       EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, tree->mem);
00198     }
00199   tree->size = 0;
00200   tree->root = 0;
00201 
00202   /* ending */
00203   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size, tree->mem);
00204   MESSAGE (EG_BBTREE_DEBUGL, "done");
00205   return 0;
00206 }
00207 
00208 /* ========================================================================= */
00209 /** @brief Given an initialized bbtree, left it at it initial state (just after
00210  * EGnewBbtree).
00211  * @param tree EGbbtree_t* pointer to the tree to be reseted to its initial
00212  * state.
00213  * @param dataFree free function for the satelite data.
00214  * @param datamem pointer to the memory pool used to allocate the satelite
00215  * data.
00216  * @return zero on success, non-zero otherwise.
00217  * @par Description:
00218  * Set the structure to its initiial state, free all internal data to the
00219  * memory pool, and apply the given free function to the satelite data.
00220  * */
00221 extern inline int EGbbtreeClearMP (EGbbtree_t * tree,
00222                                    EGfreeMP_f dataFree,
00223                                    EGmemPool_t * datamem)
00224 {
00225   /* local variables */
00226   EGbbtreeNode_t *c_node;
00227   unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00228     stack_pos = 0;
00229   EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00230                                              EGbbtreeNode_t *, stack_size);
00231 
00232   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00233   /* init the stack */
00234   stack[stack_pos] = tree->root;
00235   if (tree->size)
00236     while (~stack_pos)
00237     {
00238       c_node = stack[stack_pos];
00239       stack_pos--;
00240       if (c_node->left)
00241         stack[++stack_pos] = c_node->left;
00242       if (c_node->right)
00243         stack[++stack_pos] = c_node->right;
00244       if (dataFree)
00245         dataFree (c_node->this, datamem);
00246       EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, tree->mem);
00247     }
00248   tree->size = 0;
00249   tree->root = 0;
00250 
00251   /* ending */
00252   EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size, tree->mem);
00253   MESSAGE (EG_BBTREE_DEBUGL, "done");
00254   return 0;
00255 }
00256 
00257 
00258 /* ========================================================================= */
00259 /** @brief Find an element in the tree.
00260  * @param tree EGbbtree_t* pointer to the tree where we will perform the
00261  * search.
00262  * @param elem void* pointer to the structure that we are looking for.
00263  * @return EGbbtreeNode_t pointer to the node in the tree containing the
00264  * element, if no such node exists, return NULL.
00265  * @par Description:
00266  * This function will searxh for the element in the tree that satisfy
00267  * compare(elem,found)==0. */
00268 extern inline EGbbtreeNode_t *EGbbtreeFind (EGbbtree_t * tree,
00269                                             const void *elem)
00270 {
00271   /* local variables */
00272   EGbbtreeNode_t *c_node = tree->root;
00273   int rval = 0;
00274 
00275   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00276   /* now we iterate */
00277   while (c_node)
00278   {
00279     rval = tree->compare (elem, c_node->this);
00280     if (!rval)
00281       break;
00282     if (rval < 0)
00283       c_node = c_node->left;
00284     else
00285       c_node = c_node->right;
00286   }
00287 
00288   /* ending */
00289   MESSAGE (EG_BBTREE_DEBUGL, "done");
00290   return c_node;
00291 }
00292 
00293 /* ========================================================================= */
00294 /** @brief Add a new element to the tree.
00295  * @param tree EGbbtree_t* pointer to the tree where we will add the new
00296  * element.
00297  * @param elem void* pointer to the element to be added to the tree.
00298  * @return EGbbtreeNode_t* pointer to the newly created node containing the
00299  * inserted element, if the eement already existed, we return NULL.
00300  * @par Description:
00301  * Add a new element (according to the comopare function) to the tree and
00302  * maintain the balance on the tree. If the element is repeated on the tree, it
00303  * will return NULL.
00304  * */
00305 EGbbtreeNode_t *EGbbtreeAdd (EGbbtree_t * tree,
00306                              void *elem);
00307 
00308 /* ========================================================================= */
00309 /** @brief Delete an element from the tree.
00310  * @param tree EGbbtree_t* pointer to the tree from where we will eliminate the
00311  * given node.
00312  * @param node EGbbtreeNode_t* pointer to the node of the tree to be
00313  * eliminated.
00314  * @return zero on success, non-zero otherwise.
00315  * @par Description:
00316  * Given an initialized tree, and a ode pertaianing to it (the code won't check
00317  * this), it will eliminate the node form the tree. If an error occour, it will
00318  * return non-zero. Note that this funcion won't free the internal satelite
00319  * data of the given node, this should be done by the caller of the function
00320  * __BEFORE__ using this function.
00321  * */
00322 int EGbbtreeRemove (EGbbtree_t * tree,
00323                     EGbbtreeNode_t * node);
00324 
00325 /* ========================================================================= */
00326 /** @brief, get the predecessor of the current node.
00327  * @param node EGbbtreeNode_t* pointer to the node to wich we are looking for
00328  * its predecessor.
00329  * @return EGbbtreeNode_t* pointer to the predecessor of the given node.
00330  * @par Description:
00331  * This function try to find the predecessor of the given node, if no such
00332  * node exists, return NULL.
00333  * */
00334 extern inline EGbbtreeNode_t *EGbbtreePredecessor (EGbbtreeNode_t * node)
00335 {
00336   /* local variables */
00337   EGbbtreeNode_t *c_node = node->left,
00338    *x_node = node;
00339   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00340   if (c_node)
00341   {
00342     while (c_node->right)
00343       c_node = c_node->right;
00344     MESSAGE (EG_BBTREE_DEBUGL, "done");
00345     return c_node;
00346   }
00347   c_node = node->parent;
00348   while (c_node && x_node == c_node->left)
00349   {
00350     x_node = c_node;
00351     c_node = c_node->parent;
00352   }
00353   MESSAGE (EG_BBTREE_DEBUGL, "done");
00354   return c_node;
00355 }
00356 
00357 /* ========================================================================= */
00358 /** @brief, get the successor of the current node.
00359  * @param node EGbbtreeNode_t* pointer to the node to wich we are looking for
00360  * its successor.
00361  * @return EGbbtreeNode_t* pointer to the successor of the given node.
00362  * @par Description:
00363  * This function try to find the successor of the given node, if no such node
00364  * exists, return NULL.
00365  * */
00366 extern inline EGbbtreeNode_t *EGbbtreeSuccessor (EGbbtreeNode_t * node)
00367 {
00368   /* local variables */
00369   EGbbtreeNode_t *c_node = node->right,
00370    *x_node = node;
00371   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00372   if (c_node)
00373   {
00374     while (c_node->left)
00375       c_node = c_node->left;
00376     MESSAGE (EG_BBTREE_DEBUGL, "done");
00377     return c_node;
00378   }
00379   c_node = node->parent;
00380   while (c_node && x_node == c_node->right)
00381   {
00382     x_node = c_node;
00383     c_node = c_node->parent;
00384   }
00385   MESSAGE (EG_BBTREE_DEBUGL, "done");
00386   return c_node;
00387 }
00388 
00389 
00390 /* ========================================================================= */
00391 /** @brief Return the minimum element in the tree.
00392  * @param tree EGbbtree_t* pointer to the tree to be displayed.
00393  * @return pointer to the treeNode pointing to the minimum element.
00394  * @par Description:
00395  * Given a tree, return the minimum eloement on the tree (pointer to the
00396  * connector).
00397  * */
00398 extern inline EGbbtreeNode_t *EGbbtreeMin (EGbbtree_t * tree)
00399 {
00400   EGbbtreeNode_t *root = tree->root;
00401   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00402   while (root && root->left)
00403     root = root->left;
00404   MESSAGE (EG_BBTREE_DEBUGL, "done");
00405   return root;
00406 }
00407 
00408 /* ========================================================================= */
00409 /** @brief Return the maximum element in the tree.
00410  * @param tree EGbbtree_t* pointer to the tree to be displayed.
00411  * @return pointer to the treeNode pointing to the maximum element.
00412  * @par Description:
00413  * Given a tree, return the maximum eloement on the tree (pointer to the
00414  * connector).
00415  * */
00416 extern inline EGbbtreeNode_t *EGbbtreeMax (EGbbtree_t * tree)
00417 {
00418   EGbbtreeNode_t *root = tree->root;
00419   MESSAGE (EG_BBTREE_DEBUGL, "entering");
00420   while (root && root->right)
00421     root = root->right;
00422   MESSAGE (EG_BBTREE_DEBUGL, "done");
00423   return root;
00424 }
00425 
00426 /* ========================================================================= */
00427 /** @brief Display function for the tree.
00428  * @param tree EGbbtree_t* pointer to the tree to be displayed.
00429  * @param dataDisplay EGdisplay_f function that display the internal data (can
00430  * be NULL).
00431  * @param file FILE* pointer to the output stream.
00432  * @par Description: Display information of the tree, it's nodes, and the
00433  * internal data.
00434  * */
00435 void EGbbtreeDisplay (EGbbtree_t * tree,
00436                       EGdisplay_f dataDisplay,
00437                       FILE * file);
00438 
00439 /* ========================================================================= */
00440 /** @} */
00441 /* end of eg_bbtree.h */
00442 #endif

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