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
1.4.5