c_rbtree.h

Go to the documentation of this file.
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 */

Generated on Mon May 4 17:43:35 2009 for doc by  doxygen 1.5.6