00001 /* 00002 * libcsync -- a library to sync a directory with another 00003 * 00004 * Copyright (c) 2003-2004 by Andrew Suffield <asuffield@debian.org> 00005 * Copyright (c) 2007 by Andreas Schneider <mail@cynapses.org> 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation; either version 2 00010 * of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software Foundation, 00019 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 * 00021 * vim: ft=c.doxygen ts=2 sw=2 et cindent 00022 */ 00023 00024 /** 00025 * @file c_rbtree.h 00026 * 00027 * @brief Interface of the cynapses libc red-black tree implementation 00028 * 00029 * A red-black tree is a type of self-balancing binary search tree. It is 00030 * complex, but has good worst-case running time for its operations and is 00031 * efficient in practice: it can search, insert, and delete in O(log n) 00032 * time, where n is the number of elements in the tree. 00033 * 00034 * In red-black trees, the leaf nodes are not relevant and do not contain 00035 * data. Therefore we use a sentinal node to save memory. All references 00036 * from internal nodes to leaf nodes instead point to the sentinel node. 00037 * 00038 * In a red-black tree each node has a color attribute, the value of which 00039 * is either red or black. In addition to the ordinary requirements imposed 00040 * on binary search trees, the following additional requirements of any 00041 * valid red-black tree apply: 00042 * 00043 * 1. A node is either red or black. 00044 * 2. The root is black. 00045 * 3. All leaves are black, even when the parent is black 00046 * (The leaves are the null children.) 00047 * 4. Both children of every red node are black. 00048 * 5. Every simple path from a node to a descendant leaf contains the same 00049 * number of black nodes, either counting or not counting the null black 00050 * nodes. (Counting or not counting the null black nodes does not affect 00051 * the structure as long as the choice is used consistently.). 00052 * 00053 * These constraints enforce a critical property of red-black trees: that the 00054 * longest path from the root to a leaf is no more than twice as long as the 00055 * shortest path from the root to a leaf in that tree. The result is that the 00056 * tree is roughly balanced. Since operations such as inserting, deleting, and 00057 * finding values requires worst-case time proportional to the height of the 00058 * tree, this theoretical upper bound on the height allows red-black trees to 00059 * be efficient in the worst-case, unlike ordinary binary search trees. 00060 * 00061 * http://en.wikipedia.org/wiki/Red-black_tree 00062 * 00063 * @defgroup cynRBTreeInternals cynapses libc red-black tree functions 00064 * @ingroup cynLibraryAPI 00065 * 00066 * @{ 00067 */ 00068 #ifndef _C_RBTREE_H 00069 #define _C_RBTREE_H 00070 00071 /* Forward declarations */ 00072 struct c_rbtree_s; typedef struct c_rbtree_s c_rbtree_t; 00073 struct c_rbnode_s; typedef struct c_rbnode_s c_rbnode_t; 00074 00075 /** 00076 * Define the two colors for the red-black tree 00077 */ 00078 enum xrbcolor_e { BLACK = 0, RED }; typedef enum xrbcolor_e xrbcolor_t; 00079 00080 /** 00081 * @brief Callback function to compare a key with the data from a 00082 * red-black tree node. 00083 * 00084 * @param key key as a generic pointer 00085 * @param data data as a generic pointer 00086 * 00087 * @return It returns an integer less than, equal to, or greater than zero 00088 * depending on the key or data you use. The function is similar 00089 * to strcmp(). 00090 */ 00091 typedef int c_rbtree_compare_func(const void *key, const void *data); 00092 00093 /** 00094 * @brief Visit function for the c_rbtree_walk() function. 00095 * 00096 * This function will be called by c_rbtree_walk() for every node. It is up to 00097 * the developer what the function does. The fist parameter is a node object 00098 * the second can be of any kind. 00099 * 00100 * @param obj The node data that will be passed by c_rbtree_walk(). 00101 * @param data Generic data pointer. 00102 * 00103 * @return 0 on success, < 0 on error. You should set errno. 00104 * 00105 */ 00106 typedef int c_rbtree_visit_func(void *obj, void *data); 00107 00108 /** 00109 * Structure that represents a red-black tree 00110 */ 00111 struct c_rbtree_s { 00112 c_rbnode_t *root; 00113 c_rbtree_compare_func *key_compare; 00114 c_rbtree_compare_func *data_compare; 00115 size_t size; 00116 }; 00117 00118 /** 00119 * Structure that represents a node of a red-black tree 00120 */ 00121 struct c_rbnode_s { 00122 c_rbtree_t *tree; 00123 c_rbnode_t *left; 00124 c_rbnode_t *right; 00125 c_rbnode_t *parent; 00126 void *data; 00127 xrbcolor_t color; 00128 }; 00129 00130 /** 00131 * @brief Create the red-black tree 00132 * 00133 * @param rbtree The pointer to assign the allocated memory. 00134 * 00135 * @param key_compare Callback function to compare a key with the data 00136 * inside a reb-black tree node. 00137 * 00138 * @param data_compare Callback function to compare a key as data with thee 00139 * data inside a red-black tree node. 00140 * 00141 * @return 0 on success, -1 if an error occured with errno set. 00142 */ 00143 int c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare); 00144 00145 /** 00146 * @brief Duplicate a red-black tree. 00147 * 00148 * @param tree Tree to duplicate. 00149 * 00150 * @return Pointer to a new allocated duplicated rbtree. NULL if an error 00151 * occured. 00152 */ 00153 c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree); 00154 00155 /** 00156 * @brief Free the structure of a red-black tree. 00157 * 00158 * You should call c_rbtree_destroy() before you call this function. 00159 * 00160 * @param tree The tree to free. 00161 * 00162 * @return 0 on success, less than 0 if an error occured. 00163 */ 00164 int c_rbtree_free(c_rbtree_t *tree); 00165 00166 /** 00167 * @brief Destroy the content and the nodes of an red-black tree. 00168 * 00169 * This is far from the most efficient way to walk a tree, but it is 00170 * the *safest* way to destroy a tree - the destructor can do almost 00171 * anything (as long as it does not create an infinite loop) to the 00172 * tree structure without risk. 00173 * 00174 * If for some strange reason you need a faster destructor (think 00175 * twice - speed and memory deallocation don't mix well) then consider 00176 * stashing an llist of dataects and destroying that instead, and just 00177 * using c_rbtree_free() on your tree. 00178 * 00179 * @param T The tree to destroy. 00180 * @param DESTRUCTOR The destructor to call on a node to destroy. 00181 */ 00182 #define c_rbtree_destroy(T, DESTRUCTOR) \ 00183 do { \ 00184 if (T) { \ 00185 c_rbnode_t *_c_rbtree_temp; \ 00186 while ((_c_rbtree_temp = c_rbtree_head(T))) { \ 00187 (DESTRUCTOR)(_c_rbtree_temp->data); \ 00188 if (_c_rbtree_temp == c_rbtree_head(T)) { \ 00189 c_rbtree_node_delete(_c_rbtree_temp); \ 00190 } \ 00191 } \ 00192 } \ 00193 SAFE_FREE(T); \ 00194 } while (0); 00195 00196 /** 00197 * @brief Inserts a node into a red black tree. 00198 * 00199 * @param tree The red black tree to insert the node. 00200 * @param data The data to insert into the tree. 00201 * 00202 * @return 0 on success, 1 if a duplicate has been found and < 0 if an error 00203 * occured with errno set. 00204 * EINVAL if a null pointer has been passed as the tree. 00205 * ENOMEM if there is no memory left. 00206 */ 00207 int c_rbtree_insert(c_rbtree_t *tree, void *data); 00208 00209 /** 00210 * @brief Find a node in a red-black tree. 00211 * 00212 * c_rbtree_find() is searching for the given key in a red-black tree and 00213 * returns the node if the key has been found. 00214 * 00215 * @param tree The tree to search. 00216 * @param key The key to search for. 00217 * 00218 * @return If the key was found the node will be returned. On error NULL 00219 * will be returned. 00220 */ 00221 c_rbnode_t *c_rbtree_find(c_rbtree_t *tree, const void *key); 00222 00223 /** 00224 * @brief Get the head of the red-black tree. 00225 * 00226 * @param tree The tree to get the head for. 00227 * 00228 * @return The head node. NULL if an error occured. 00229 */ 00230 c_rbnode_t *c_rbtree_head(c_rbtree_t *tree); 00231 00232 /** 00233 * @brief Get the tail of the red-black tree. 00234 * 00235 * @param tree The tree to get the tail for. 00236 * 00237 * @return The tail node. NULL if an error occured. 00238 */ 00239 c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree); 00240 00241 /** 00242 * @brief Get the size of the red-black tree. 00243 * 00244 * @param T The tree to get the size from. 00245 * 00246 * @return The size of the red-black tree. 00247 */ 00248 #define c_rbtree_size(T) (T) == NULL ? 0 : ((T)->size) 00249 00250 /** 00251 * @brief Walk over a red-black tree. 00252 * 00253 * Walk over a red-black tree calling a visitor function for each node found. 00254 * 00255 * @param tree Tree to walk. 00256 * @param data Data which should be passed to the visitor function. 00257 * @param visitor Visitor function. This will be called for each node passed. 00258 * 00259 * @return 0 on sucess, less than 0 if an error occured. 00260 */ 00261 int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor); 00262 00263 /** 00264 * @brief Delete a node in a red-black tree. 00265 * 00266 * @param node Node which should be deleted. 00267 * 00268 * @return 0 on success, -1 if an error occured. 00269 */ 00270 int c_rbtree_node_delete(c_rbnode_t *node); 00271 00272 /** 00273 * @brief Get the next node. 00274 * 00275 * @param node The node of which you want the next node. 00276 * 00277 * @return The next node, NULL if an error occured. 00278 */ 00279 c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node); 00280 00281 /** 00282 * @brief Get the previous node. 00283 * 00284 * @param node The node of which you want the previous node. 00285 * 00286 * @return The previous node, NULL if an error occured. 00287 */ 00288 c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node); 00289 00290 /** 00291 * @brief Get the data of a node. 00292 * 00293 * @param N The node to get the data from. 00294 * 00295 * @return The data, NULL if an error occured. 00296 */ 00297 #define c_rbtree_node_data(N) ((N) ? ((N)->data) : NULL) 00298 00299 /** 00300 * @brief Perform a sanity check for a red-black tree. 00301 * 00302 * This is mostly for testing purposes. 00303 * 00304 * @param tree The tree to check. 00305 * 00306 * @return 0 on success, less than 0 if an error occured. 00307 */ 00308 int c_rbtree_check_sanity(c_rbtree_t *tree); 00309 00310 /** 00311 * }@ 00312 */ 00313 #endif /* _C_RBTREE_H */