红黑树与C实现算法 - RedBlackTree.c


本文全部内容摘自互联网,作者根据需要做了修改和补充,最主要的是提供了对set的支持,并且给出完整的测试用例。

红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。

红黑树是一种很有意思的平衡检索树。它的统计性能要好于平衡二叉树(有些书籍根据作者姓名,Adelson-Velskii和Landis,将其称为AVL-树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。

红黑树的实现代码如下(red_black_tree.h,red_black_tree.c和测试文件rbtree_test.c):

  1. /****************************************************************************** 
  2. * red_black_tree.h                                                            * 
  3. * Download From:                                                              * 
  4. *    http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03/code/rbtree/   * 
  5. * Last Edited by:                                                             * 
  6. *    cheungmine                                                               * 
  7. * 2010-8                                                                      * 
  8. * Container class for a red-black tree: A binary tree that satisfies the      * 
  9. * following properties:                                                       * 
  10. * 1. Each node has a color, which is either red or black.                     * 
  11. * 2. A red node cannot have a red parent.                                     * 
  12. * 3. The number of black nodes from every path from the tree root to a leaf   * 
  13. *    is the same for all tree leaves (it is called the 'black depth' of the   * 
  14. *    tree).                                                                   * 
  15. * Due to propeties 2-3, the depth of a red-black tree containing n nodes      * 
  16. * is bounded by 2*log_2(n).                                                   *           
  17. *                                                                             * 
  18. * The red_black_tree_t template requires two template parmeters:              * 
  19. * - The contained TYPE class represents the objects stored in the tree.       * 
  20. *   It has to support the copy constructor and the assignment operator        * 
  21. *   (operator=).                                                              * 
  22. *                                                                             * 
  23. * - pfcbRBTreeCompFunc is a functor used to define the order of objects of    * 
  24. *   class TYPE:                                                               * 
  25. *   This class has to support an operator() that recieves two objects from    * 
  26. *   the TYPE class and returns a negative, zero or a positive integer,        * 
  27. *   depending on the comparison result.                                       * 
  28. ******************************************************************************/  
  29. #ifndef RED_BLACK_TREE_H   
  30. #define RED_BLACK_TREE_H   
  31. /*! 
  32.  * Define RBTREE_SUPPORTS_MULTI_OBJECTS for supporting mapset (multi-key-map) 
  33.  * if RBTREE_SUPPORTS_MULTI_OBJECTS defined, object must inherit from struct 
  34.  * rbtree_object_base. That means the first member of object must be a struct 
  35.  * pointer to next possible object if it has. 
  36.  * 
  37.  * #define  RBTREE_SUPPORTS_MULTI_OBJECTS 
  38.  */  
  39. #define  RBTREE_SUPPORTS_MULTI_OBJECTS   
  40. #ifdef RBTREE_SUPPORTS_MULTI_OBJECTS   
  41.     typedef struct _rbtree_object_base {  
  42.         struct _rbtree_object_base *__next_object;  
  43.     }rbtree_object_base;  
  44. #endif   
  45. /*! Color enumeration for nodes of red-black tree */  
  46. typedef enum _red_black_color_enum   
  47. {  
  48.     rbcRed,   
  49.     rbcBlack  
  50. } red_black_color_enum;  
  51. /*! Representation of a node in a red-black tree */  
  52. typedef struct _red_black_node_t {  
  53.     void                     * object;       /* the stored object user defined */  
  54.     red_black_color_enum       color;        /* the color of the node */  
  55.     struct _red_black_node_t * parent;       /* points to the parent node */  
  56.     struct _red_black_node_t * right;        /* points to the right child */  
  57.     struct _red_black_node_t * left;         /* points to the left child */  
  58. } red_black_node_t;  
  59. /*! Callback function prototype for comparing objects */  
  60. typedef int (pfcbRBTreeCompFunc)(void *object1, void *object2);  
  61. /*! Callback function prototype for traverse objects */  
  62. typedef void(pfcbRBTreeOperFunc)(void *object,  void *param);  
  63.     
  64. /*! Construct of a red-black tree node 
  65.  *  param object The object stored in the node 
  66.  *  param color The color of the node 
  67.  */  
  68. extern red_black_node_t * rbnode_construct(void * object, red_black_color_enum color);  
  69. /*! Recursive destructor for the entire sub-tree */  
  70. extern void rbnode_destruct(red_black_node_t * node);  
  71. /*! Calculate the depth of the sub-tree spanned by the given node 
  72.  *  param node The sub-tree root 
  73.  *  return The sub-tree depth 
  74.  */  
  75. extern int rbnode_depth(red_black_node_t * node);  
  76. /*! Get the leftmost node in the sub-tree spanned by the given node 
  77.  *  param node The sub-tree root 
  78.  *  return The sub-tree minimum 
  79.  */  
  80. extern red_black_node_t * rbnode_minimum(red_black_node_t * node);  
  81. /*! Get the rightmost node in the sub-tree spanned by the given node 
  82.  *  param node The sub-tree root 
  83.  *  return The sub-tree maximum 
  84.  */  
  85. extern red_black_node_t * rbnode_maximum(red_black_node_t * node);  
  86. /*! Replace the object */  
  87. extern void rbnode_replace(red_black_node_t * node, void * object);  
  88. /*! Get the next node in the tree (according to the tree order) 
  89.  *  param node The current node 
  90.  *  return The successor node, or NULL if node is the tree maximum 
  91.  */  
  92. extern red_black_node_t * rbnode_successor(red_black_node_t * node);  
  93. /*! Get the previous node in the tree (according to the tree order) 
  94.  *  param node The current node 
  95.  *  return The predecessor node, or NULL if node is the tree minimum 
  96.  */  
  97. extern red_black_node_t * rbnode_predecessor(red_black_node_t * node);  
  98. /*! Duplicate the entire sub-tree rooted at the given node 
  99.  *  param node The sub-tree root 
  100.  *  return A pointer to the duplicated sub-tree root 
  101.  */  
  102. extern red_black_node_t * rbnode_duplicate(red_black_node_t * node);  
  103. /*! Traverse a red-black sub-tree left first 
  104.  *  param node The sub-tree root 
  105.  *  param op The operation to perform on each object in the sub-tree 
  106.  */  
  107. extern void rbnode_traverse(red_black_node_t *node, pfcbRBTreeOperFunc *opFunc, void *param);  
  108. /*! Traverse a red-black sub-tree right first 
  109.  */  
  110. extern void rbnode_traverse_right(red_black_node_t *node, pfcbRBTreeOperFunc *opFunc, void*param);  
  111. /*! Representation of a red-black tree */  
  112. typedef struct _red_black_tree_t {  
  113.     red_black_node_t   * root;                /* pointer to the tree root */  
  114.     int                  iSize;               /* number of objects stored */  
  115.     pfcbRBTreeCompFunc * comp;                /* compare function */  
  116. } red_black_tree_t;  
  117. /*! Initialize a red-black tree with a comparision function 
  118.  *  param tree The tree 
  119.  *  param comp The comparision function 
  120.  */  
  121. void rbtree_init(red_black_tree_t * tree, pfcbRBTreeCompFunc * comp);  
  122. /*! Construct a red-black tree with a comparison object 
  123.  *  param comp A pointer to the comparison object to be used by the tree 
  124.  *  return The newly constructed  tree 
  125.  */  
  126. red_black_tree_t * rbtree_construct(pfcbRBTreeCompFunc * comp);  
  127. /*! Clean a red-black tree [takes O(n) operations] 
  128.  *  param tree The tree 
  129.  */  
  130. extern void rbtree_clean(red_black_tree_t * tree);  
  131. /*! Destruct a red-black tree 
  132.  *  param tree The tree 
  133.  */  
  134. extern void rbtree_destruct(red_black_tree_t * tree);  
  135. /*! Get the size of the tree [takes O(1) operations] 
  136.  *  param tree The tree 
  137.  *  return The number of objects stored in the tree 
  138.  */  
  139. extern int rbtree_size(red_black_tree_t * tree);  
  140. /*! Get the depth of the tree [takes O(n) operations] 
  141.  *  param tree The tree 
  142.  *  return The length of the longest path from the root to a leaf node 
  143.  */  
  144. extern int rbtree_depth(red_black_tree_t * tree);  
  145. /*! Check whether the tree contains an object [takes O(log n) operations] 
  146.  *  param tree The tree 
  147.  *  param object The query object 
  148.  *  return (true) if an equal object is found in the tree, otherwise (false) 
  149.  */  
  150. extern int rbtree_contains(red_black_tree_t * tree, void * object);  
  151. /*! Insert an object to the tree [takes O(log n) operations] 
  152.  *  param tree The tree 
  153.  *  param object The object to be inserted 
  154.  *  return the inserted object node 
  155.  */  
  156. extern red_black_node_t * rbtree_insert(red_black_tree_t * tree, void * object);  
  157. /*! Insert an unique object to the tree */  
  158. extern red_black_node_t * rbtree_insert_unique(red_black_tree_t * tree, void * object);  
  159. /*! Insert a new object to the tree as the a successor of a given node 
  160.  *  param tree The tree 
  161.  *  return The new node 
  162.  */  
  163. extern red_black_node_t * insert_successor_at(red_black_tree_t * tree,  
  164.                                             red_black_node_t * at_node,  
  165.                                             void * object);  
  166. /*! Insert a new object to the tree as the a predecessor of a given node 
  167.  *  param tree The tree 
  168.  *  return The new node 
  169.  */  
  170. extern red_black_node_t * insert_predecessor_at(red_black_tree_t * tree,  
  171.                                               red_black_node_t * at_node,  
  172.                                               void * object);  
  173. /*! Remove an object from the tree [takes O(log n) operations] 
  174.  *  param tree The tree 
  175.  *  param object The object to be removed 
  176.  *  pre The object should be contained in the tree 
  177.  */  
  178. extern void rbtree_remove(red_black_tree_t * tree, void * object);  
  179. /*! Get a handle to the tree minimum [takes O(log n) operations] 
  180.  *  param tree The tree 
  181.  *  return the minimal object in the tree, or a NULL if the tree is empty 
  182.  */  
  183. extern red_black_node_t * rbtree_minimum(red_black_tree_t * tree);  
  184. /*! Get a handle to the tree maximum [takes O(log n) operations] 
  185.  *  param tree The tree 
  186.  *  return the maximal object in the tree, or a NULL if the tree is empty 
  187.  */  
  188. extern red_black_node_t * rbtree_maximum(red_black_tree_t * tree);  
  189. /*! Get the next node in the tree (according to the tree order) 
  190.  * [takes O(log n) operations at worst-case, but only O(1) amortized] 
  191.  *  param tree The tree 
  192.  *  param node The current object 
  193.  *  return The successor node, or a NULL, if we are at the tree maximum 
  194.  */  
  195. extern red_black_node_t * rbtree_successor(red_black_tree_t * tree,  
  196.                                            red_black_node_t * node);  
  197. /*! Get the previous node in the tree (according to the tree order) 
  198.  * [takes O(log n) operations at worst-case, but only O(1) amortized] 
  199.  *  param tree The tree 
  200.  *  param node The current object 
  201.  *  return The predecessor node, or a NULL, if we are at the tree minimum 
  202.  */  
  203. extern red_black_node_t * rbtree_predecessor(red_black_tree_t * tree,  
  204.                                              red_black_node_t * node);  
  205. /*! Find a node that contains the given object 
  206.  *  param tree The tree 
  207.  *  param object The desired object 
  208.  *  return A node that contains the given object, or NULL if no such object 
  209.  * is found in the tree 
  210.  */  
  211. extern red_black_node_t * rbtree_find(red_black_tree_t * tree, void * object);  
  212. /*! Remove the object stored in the given tree node  
  213.  *  param tree The tree 
  214.  *  param node The node storing the object to be removed from the tree 
  215.  */  
  216. extern void rbtree_remove_at(red_black_tree_t * tree, red_black_node_t * node);  
  217. /*! Left-rotate the sub-tree spanned by the given node 
  218.  *  param tree The tree 
  219.  *  param node The sub-tree root 
  220.  */  
  221. extern void rbtree_rotate_left(red_black_tree_t * tree, red_black_node_t * node);  
  222. /*! Right-rotate the sub-tree spanned by the given node 
  223.  *  param tree The tree 
  224.  *  param node The sub-tree root 
  225.  */  
  226. extern void rbtree_rotate_right(red_black_tree_t * tree, red_black_node_t * node);  
  227. /*! 
  228.  * Fix-up the red-black tree properties after an insertion operation 
  229.  *  param tree The tree 
  230.  *  param node The node that has just been inserted to the tree 
  231.  *  pre The color of node must be red 
  232.  */  
  233. extern void rbtree_insert_fixup(red_black_tree_t * tree, red_black_node_t * node);  
  234. /*! Fix-up the red-black tree properties after a removal operation 
  235.  *  param tree The tree 
  236.  *  param node The child of the node that has just been removed from the tree 
  237.  */  
  238. extern void rbtree_remove_fixup(red_black_tree_t * tree, red_black_node_t * node);  
  239. /*! Traverse a red-black tree left first 
  240.  *  param tree The tree 
  241.  *  param op The operation to perform on every object of the tree (according to 
  242.  * the tree order) 
  243.  */  
  244. extern void rbtree_traverse(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param);  
  245. #define rbtree_traverse_left rbtree_traverse   
  246. /*! Traverse a red-black tree right first */  
  247. extern void rbtree_traverse_right(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param);  
  248. #endif /* RED_BLACK_TREE_H */  

----------------------------

  1. /****************************************************************************** 
  2. * red_black_tree.c                                                            * 
  3. * Download From:                                                              * 
  4. *    http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03/code/rbtree/   * 
  5. * Last Edited by: cheungmine                                                  * 
  6. ******************************************************************************/  
  7. #include <stdio.h>   
  8. #include <stdlib.h>   
  9. #include <assert.h>   
  10. #include "red_black_tree.h"   
  11. /*! 
  12.  * Operations on red_black_node_t struct 
  13.  */  
  14. /* Construct a red-black tree node */  
  15. red_black_node_t * rbnode_construct(void * object, red_black_color_enum color)  
  16. {  
  17.     red_black_node_t * node = (red_black_node_t *) malloc(sizeof(red_black_node_t));  
  18.     if (!node) {  
  19.         fprintf(stderr, "Not enough memory!/n");  
  20.         return NULL;  
  21.     }  
  22.     node->object = object;  
  23.     node->color = color;  
  24.     node->parent = node->right = node->left = NULL;  
  25.     return node;  
  26. }  
  27. /* Destructor of a red-black tree node */  
  28. void rbnode_destruct(red_black_node_t * node)  
  29. {  
  30.     if (!node) return;  
  31.     rbnode_destruct(node->right);  
  32.     rbnode_destruct(node->left);  
  33.     free(node);  
  34. }  
  35. /* Calculate the depth of the subtree spanned by a given node */  
  36. int rbnode_depth(red_black_node_t * node)  
  37. {  
  38.     /* Recursively calculate the depth of the left and right sub-trees */  
  39.     int  iRightDepth = (node->right) ? rbnode_depth(node->right) : 0;  
  40.     int  iLeftDepth = (node->left) ? rbnode_depth(node->left) : 0;  
  41.     /* Return the maximal child depth + 1 (the current node) */  
  42.     return ((iRightDepth > iLeftDepth) ? (iRightDepth + 1) : (iLeftDepth + 1));  
  43. }  
  44. /* Return the leftmost leaf in the tree */  
  45. red_black_node_t * rbnode_minimum(red_black_node_t * node)  
  46. {  
  47.     while (node->left)  
  48.         node = node->left;  
  49.     return node;  
  50. }  
  51. /* Return the rightmost leaf in the tree */  
  52. red_black_node_t * rbnode_maximum(red_black_node_t * node)  
  53. {  
  54.     while (node->right)  
  55.         node = node->right;  
  56.     return node;  
  57. }  
  58. /* Replace the object */  
  59. void rbnode_replace(red_black_node_t * node, void * object)  
  60. {  
  61.     /* Make sure the replacement does not violate the tree order */  
  62.     /* Replace the object at node */  
  63.     node->object = object;  
  64. }  
  65.           
  66. /* Get the next node in the tree (according to the tree order) */  
  67. red_black_node_t * rbnode_successor(red_black_node_t * node)  
  68. {  
  69.     red_black_node_t * succ_node;  
  70.     if (node->right) {  
  71.         /* If there is a right child, the successor is the minimal object in  
  72.          * the sub-tree spanned by this child. 
  73.          */  
  74.         succ_node = node->right;  
  75.         while (succ_node->left)  
  76.             succ_node = succ_node->left;  
  77.     }   
  78.     else {  
  79.         /* Otherwise, go up the tree until reaching the parent from the left  
  80.          * direction. 
  81.          */  
  82.         red_black_node_t * prev_node = node;  
  83.         succ_node = node->parent;  
  84.         while (succ_node && prev_node == succ_node->right) {  
  85.             prev_node = succ_node;  
  86.             succ_node = succ_node->parent;  
  87.         }  
  88.     }  
  89.     return (succ_node);  
  90. }  
  91. /* Get the previous node in the tree (according to the tree order) */  
  92. red_black_node_t * rbnode_predecessor(red_black_node_t * node)  
  93. {  
  94.     red_black_node_t * pred_node;  
  95.     if (node->left) {  
  96.         /* If there is a left child, the predecessor is the maximal object in  
  97.          * the sub-tree spanned by this child. 
  98.          */  
  99.         pred_node = node->left;  
  100.         while (pred_node->right)  
  101.             pred_node = pred_node->right;  
  102.     } else {  
  103.         /* Otherwise, go up the tree until reaching the parent from the right  
  104.          * direction. 
  105.          */  
  106.         red_black_node_t * prev_node = node;  
  107.         pred_node = node->parent;  
  108.         while (pred_node && prev_node == pred_node->left) {  
  109.             prev_node = pred_node;  
  110.             pred_node = pred_node->parent;  
  111.         }  
  112.     }  
  113.     return (pred_node);  
  114. }  
  115. /* Return a pointer to a duplication of the given node */  
  116. red_black_node_t * rbnode_duplicate(red_black_node_t * node)  
  117. {  
  118.     /* Create a node of the same color, containing the same object */  
  119.     red_black_node_t * dup_node = rbnode_construct(node->object, node->color);  
  120.     if (!dup_node) return NULL;  
  121.     /* Duplicate the children recursively */  
  122.     if (node->right) {  
  123.         dup_node->right = rbnode_duplicate (node->right);  
  124.         dup_node->right->parent = dup_node;  
  125.     } else {  
  126.         dup_node->right = NULL;  
  127.     }  
  128.     if (node->left) {  
  129.         dup_node->left = rbnode_duplicate(node->left);  
  130.         dup_node->left->parent = dup_node;  
  131.     } else {  
  132.         dup_node->left = NULL;  
  133.     }  
  134.     return dup_node;                      /* Return the duplicated node */  
  135. }  
  136. /* Traverse a red-black subtree */  
  137. void rbnode_traverse(red_black_node_t * node, pfcbRBTreeOperFunc * opFunc, void* param)  
  138. {  
  139.     if (!node) return;  
  140.     rbnode_traverse(node->left, opFunc, param);  
  141.     opFunc(node->object, param);  
  142.     rbnode_traverse(node->right, opFunc, param);  
  143. }  
  144. /* Right-first traverse a red-black subtree */  
  145. void rbnode_traverse_right(red_black_node_t * node, pfcbRBTreeOperFunc * opFunc, void* param)  
  146. {  
  147.     if (!node) return;  
  148.     rbnode_traverse_right(node->right, opFunc, param);  
  149.     opFunc(node->object, param);  
  150.     rbnode_traverse_right(node->left, opFunc, param);  
  151. }  
  152. /* 
  153.  * Operations on red_black_tree_t struct 
  154.  */  
  155. /* Intialize a tree */  
  156. void rbtree_init(red_black_tree_t * tree, pfcbRBTreeCompFunc * comp)  
  157. {  
  158.     tree->comp = comp;  
  159.     tree->iSize = 0;  
  160.     tree->root = NULL;  
  161. }  
  162. /* Construct a tree given a comparison function */  
  163. red_black_tree_t * rbtree_construct(pfcbRBTreeCompFunc * comp)  
  164. {  
  165.     red_black_tree_t * tree = (red_black_tree_t *) malloc(sizeof(red_black_tree_t));  
  166.     if (!tree) {  
  167.         fprintf(stderr, "Not enough memory!/n");  
  168.         return NULL;  
  169.     }  
  170.     rbtree_init(tree, comp);  
  171.     return tree;  
  172. }  
  173. /* Remove all objects from a black-red tree */  
  174. void rbtree_clean(red_black_tree_t * tree)  
  175. {  
  176.     if (tree->root)  
  177.         rbnode_destruct(tree->root);  
  178.     tree->root = NULL;  
  179.     tree->iSize = 0;  
  180. }  
  181. /* Destruct a red-black tree */  
  182. void rbtree_destruct(red_black_tree_t * tree)  
  183. {  
  184.     rbtree_clean(tree);  
  185.     free(tree);  
  186. }  
  187. /* Returns the size of the tree */  
  188. int rbtree_size(red_black_tree_t * tree)  
  189. {  
  190.     return tree->iSize;  
  191. }  
  192. /* Returns the depth of the tree */  
  193. int rbtree_depth(red_black_tree_t * tree)  
  194. {  
  195.     if (!(tree->root))  
  196.         return 0;  
  197.     return rbnode_depth(tree->root);  
  198. }  
  199. /* Check whether the tree contains an object */  
  200. int rbtree_contains(red_black_tree_t * tree, void * object)  
  201. {  
  202.     return (rbtree_find(tree, object) != NULL);  
  203. }  
  204. /* Insert an object to the tree */  
  205. red_black_node_t * rbtree_insert(red_black_tree_t * tree, void * object)  
  206. {  
  207.     int cmp;  
  208.     red_black_node_t * cur_node;  
  209.     red_black_node_t * new_node = NULL;  
  210.     
  211.     if (!(tree->root)) {  
  212.         /* Assign a new root node. Notice that the root is always black */  
  213.         new_node = rbnode_construct(object, rbcBlack);  
  214.         if (!new_node) return NULL;  
  215.         tree->root = new_node;  
  216.         tree->iSize = 1;  
  217.         return new_node;  
  218.     }  
  219.     /* Find a place for the new object, and insert it as a red leaf */  
  220.     cur_node = tree->root;  
  221.       
  222.     while (cur_node) {  
  223.         cmp = (*(tree->comp))(object, cur_node->object);  
  224. #ifdef RBTREE_SUPPORTS_MULTI_OBJECTS   
  225.         if (cmp==0) {  
  226.             if (cur_node->object != object)  
  227.                 ((rbtree_object_base*)cur_node->object)->__next_object = (rbtree_object_base*)object;  
  228.             return cur_node;  
  229.         }  
  230. #endif   
  231.         /* Compare inserted object with the object stored in the current node */  
  232.         if (cmp > 0) {  
  233.             if (!(cur_node->left)) {  
  234.                 /* Insert the new leaf as the left child of the current node */  
  235.                 new_node = rbnode_construct(object, rbcRed);  
  236.                 if (!new_node) return NULL;  
  237.                 cur_node->left = new_node;  
  238.                 new_node->parent = cur_node;  
  239.                 cur_node = NULL;                /* terminate the while loop */  
  240.             } else {  
  241.                 cur_node = cur_node->left;      /* Go to the left sub-tree */  
  242.             }  
  243.         } else {  
  244.             if (!(cur_node->right)) {  
  245.                 /* Insert the new leaf as the right child of the current node */  
  246.                 new_node = rbnode_construct(object, rbcRed);  
  247.                 if (!new_node) return NULL;  
  248.                 cur_node->right = new_node;  
  249.                 new_node->parent = cur_node;  
  250.                 cur_node = NULL;                /* terminate the while loop */  
  251.             } else {  
  252.                 cur_node = cur_node->right;     /* Go to the right sub-tree */  
  253.             }  
  254.         }  
  255.     }  
  256.     /* Mark that a new node was added */  
  257.     tree->iSize++;  
  258.     /* Fix up the tree properties */  
  259.     rbtree_insert_fixup(tree, new_node);    
  260.     return new_node;  
  261. }  
  262. /* Insert an unique object to the tree */  
  263. red_black_node_t * rbtree_insert_unique(red_black_tree_t * tree, void * object)  
  264. {  
  265.     int cmp;  
  266.     red_black_node_t * cur_node;  
  267.     red_black_node_t * new_node = NULL;  
  268.     
  269.     if (!(tree->root)) {  
  270.         /* Assign a new root node. Notice that the root is always black */  
  271.         new_node = rbnode_construct(object, rbcBlack);  
  272.         if (!new_node) return NULL;  
  273.         tree->root = new_node;  
  274.         tree->iSize = 1;  
  275.         return new_node;  
  276.     }  
  277.     /* Find a place for the new object, and insert it as a red leaf */  
  278.     cur_node = tree->root;  
  279.     while (cur_node) {  
  280.         cmp = (*(tree->comp))(object, cur_node->object);  
  281.         if (cmp==0) {  
  282.             /* there already has an object with the same id as object to be inserted */  
  283.             return cur_node;  
  284.         }  
  285.         /* Compare inserted object with the object stored in the current node */  
  286.         if (cmp > 0) {  
  287.             if (!(cur_node->left)) {  
  288.                 /* Insert the new leaf as the left child of the current node */  
  289.                 new_node = rbnode_construct(object, rbcRed);  
  290.                 if (!new_node)   
  291.                     return NULL;  
  292.                 cur_node->left = new_node;  
  293.                 new_node->parent = cur_node;  
  294.                 cur_node = NULL;                /* terminate the while loop */  
  295.             } else {  
  296.                 cur_node = cur_node->left;      /* Go to the left sub-tree */  
  297.             }  
  298.         } else {  
  299.             if (!(cur_node->right)) {  
  300.                 /* Insert the new leaf as the right child of the current node */  
  301.                 new_node = rbnode_construct(object, rbcRed);  
  302.                 if (!new_node)   
  303.                     return NULL;  
  304.                 cur_node->right = new_node;  
  305.                 new_node->parent = cur_node;  
  306.                 cur_node = NULL;                /* terminate the while loop */  
  307.             } else {  
  308.                 cur_node = cur_node->right;     /* Go to the right sub-tree */  
  309.             }  
  310.         }  
  311.     }  
  312.     /* Mark that a new node was added */  
  313.     tree->iSize++;  
  314.     /* Fix up the tree properties */  
  315.     rbtree_insert_fixup(tree, new_node);    
  316.     return new_node;  
  317. }  
  318. /* Insert a new object to the tree as the a successor of a given node */  
  319. red_black_node_t * insert_successor_at(red_black_tree_t * tree,  
  320.                                      red_black_node_t * at_node, void * object)  
  321. {  
  322.     red_black_node_t * parent;  
  323.     red_black_node_t * new_node;  
  324.     
  325.     if (!(tree->root)) {  
  326.         /* Assign a new root node. Notice that the root is always black */  
  327.         new_node = rbnode_construct(object, rbcBlack);  
  328.         if (!new_node) return NULL;  
  329.         tree->root = new_node;  
  330.         tree->iSize = 1;  
  331.         return new_node;  
  332.     }  
  333.     /* Insert the new object as a red leaf, being the successor of node */  
  334.     new_node = rbnode_construct(object, rbcRed);  
  335.     if (!new_node) return NULL;  
  336.     if (!at_node) {  
  337.         /* The new node should become the tree minimum: Place is as the left 
  338.          * child of the current minimal leaf. 
  339.          */  
  340.         parent = rbnode_minimum(tree->root);  
  341.         parent->left = new_node;  
  342.     } else {  
  343.         /* Make sure the insertion does not violate the tree order */  
  344.         /* In case given node has no right child, place the new node as its  
  345.          * right child. Otherwise, place it at the leftmost position at the 
  346.          * sub-tree rooted at its right side. 
  347.          */  
  348.         if (!at_node->right) {  
  349.             parent = at_node;  
  350.             parent->right = new_node;  
  351.         } else {  
  352.             parent = rbnode_minimum(at_node->right);  
  353.             parent->left = new_node;  
  354.         }  
  355.     }  
  356.     new_node->parent = parent;  
  357.     /* Mark that a new node was added */  
  358.     tree->iSize++;  
  359.     /* Fix up the tree properties */  
  360.     rbtree_insert_fixup(tree, new_node);    
  361.     return new_node;  
  362. }  
  363. /* Insert a new object to the tree as the a predecessor of a given node */  
  364. red_black_node_t * insert_predecessor_at(red_black_tree_t * tree,  
  365.                                        red_black_node_t * at_node, void * object)  
  366. {  
  367.     red_black_node_t * parent;  
  368.     red_black_node_t * new_node;  
  369.     
  370.     if (!(tree->root)) {  
  371.         /* Assign a new root node. Notice that the root is always black */  
  372.         new_node = rbnode_construct(object, rbcBlack);  
  373.         if (!new_node) return NULL;  
  374.         tree->root = new_node;  
  375.         tree->iSize = 1;  
  376.         return new_node;  
  377.     }  
  378.     /* Insert the new object as a red leaf, being the predecessor of at_node */  
  379.     new_node = rbnode_construct(object, rbcRed);  
  380.     if (!new_node) return NULL;  
  381.     if (!at_node) {  
  382.         /* The new node should become the tree maximum: Place is as the right 
  383.          * child of the current maximal leaf. 
  384.          */  
  385.         parent = rbnode_maximum(tree->root);  
  386.         parent->right = new_node;  
  387.     } else {  
  388.         /* Make sure the insertion does not violate the tree order */  
  389.         /* In case given node has no left child, place the new node as its  
  390.          * left child. Otherwise, place it at the rightmost position at the 
  391.          * sub-tree rooted at its left side. 
  392.          */  
  393.         if (!(at_node->left)) {  
  394.             parent = at_node;  
  395.             parent->left = new_node;  
  396.         } else {  
  397.             parent = rbnode_maximum (at_node->left);  
  398.             parent->right = new_node;  
  399.         }  
  400.     }  
  401.     new_node->parent = parent;  
  402.     /* Mark that a new node was added */  
  403.     tree->iSize++;  
  404.     /* Fix up the tree properties */  
  405.     rbtree_insert_fixup(tree, new_node);    
  406.     return new_node;  
  407. }  
  408. /* Remove an object from the tree */  
  409. void rbtree_remove(red_black_tree_t * tree, void * object)  
  410. {  
  411.     red_black_node_t * node = rbtree_find(tree, object);    /* find the node */  
  412.     rbtree_remove_at(tree, node);                         /* remove the node */  
  413. }  
  414. /* Remove the object pointed by the given node. */  
  415. void rbtree_remove_at(red_black_tree_t * tree, red_black_node_t * node)  
  416. {  
  417.     red_black_node_t * child = NULL;  
  418.     /* In case of deleting the single object stored in the tree, free the root, 
  419.      * thus emptying the tree. 
  420.      */  
  421.     if (tree->iSize == 1) {  
  422.         rbnode_destruct(tree->root);  
  423.         tree->root = NULL;  
  424.         tree->iSize = 0;  
  425.         return;  
  426.     }  
  427.     /* Remove the given node from the tree */  
  428.     if (node->left && node->right) {  
  429.         /* If the node we want to remove has two children, find its successor, 
  430.          * which is the leftmost child in its right sub-tree and has at most 
  431.          * one child (it may have a right child). 
  432.          */  
  433.         red_black_node_t * succ_node = rbnode_minimum(node->right);  
  434.         /* Now physically swap node and its successor. Notice this may temporarily 
  435.          * violate the tree properties, but we are going to remove node anyway. 
  436.          * This way we have moved node to a position were it is more convinient 
  437.          * to delete it. 
  438.          */  
  439.         int immediate_succ = (node->right == succ_node);  
  440.         red_black_node_t * succ_parent = succ_node->parent;  
  441.         red_black_node_t * succ_left = succ_node->left;  
  442.         red_black_node_t * succ_right = succ_node->right;  
  443.         red_black_color_enum succ_color = succ_node->color;  
  444.         succ_node->parent = node->parent;  
  445.         succ_node->left = node->left;  
  446.         succ_node->right = immediate_succ ? node : node->right;  
  447.         succ_node->color = node->color;  
  448.         node->parent = immediate_succ ? succ_node : succ_parent;  
  449.         node->left = succ_left;  
  450.         node->right = succ_right;  
  451.         node->color = succ_color;  
  452.         if (!immediate_succ) {   
  453.             if (succ_node == node->parent->left)  
  454.                 node->parent->left = node;  
  455.             else  
  456.                 node->parent->right = node;  
  457.         }  
  458.         if (node->left)  
  459.             node->left->parent = node;  
  460.         if (node->right)  
  461.             node->right->parent = node;  
  462.         if (succ_node->parent) {  
  463.             if (node == succ_node->parent->left)  
  464.                 succ_node->parent->left = succ_node;  
  465.             else  
  466.                 succ_node->parent->right = succ_node;  
  467.         } else {  
  468.             tree->root = succ_node;  
  469.         }  
  470.         if (succ_node->left)  
  471.             succ_node->left->parent = succ_node;  
  472.         if (succ_node->right)  
  473.             succ_node->right->parent = succ_node;  
  474.     }  
  475.     /* At this stage, the node we are going to remove has at most one child */  
  476.     child = (node->left) ? node->left : node->right;  
  477.     /* Splice out the node to be removed, by linking its parent straight to the  
  478.      * removed node's single child. 
  479.      */  
  480.     if (child)  
  481.         child->parent = node->parent;  
  482.       
  483.     if (!(node->parent)) {  
  484.         /* If we are deleting the root, make the child the new tree node */  
  485.         tree->root = child;  
  486.     } else {  
  487.         /* Link the removed node parent to its child */  
  488.         if (node == node->parent->left) {  
  489.             node->parent->left = child;  
  490.         } else {  
  491.             node->parent->right = child;  
  492.         }  
  493.     }  
  494.     /* Fix-up the red-black properties that may have been damaged: If we have 
  495.      * just removed a black node, the black-depth property is no longer valid. 
  496.      */  
  497.     if (node->color == rbcBlack && child)  
  498.         rbtree_remove_fixup(tree, child);  
  499.     /* Delete the un-necessary node (we nullify both its children because the  
  500.      * node's destructor is recursive). 
  501.      */  
  502.     node->left = NULL;  
  503.     node->right = NULL;  
  504.     free(node);  
  505.     /* Descrease the number of objects in the tree */  
  506.     tree->iSize--;  
  507. }  
  508. /* Get the tree minimum */  
  509. red_black_node_t * rbtree_minimum(red_black_tree_t * tree)  
  510. {  
  511.     if (!(tree->root))  
  512.         return NULL;  
  513.     /* Return the leftmost leaf in the tree */  
  514.     return rbnode_minimum(tree->root);  
  515. }  
  516. /* Get the tree maximum */  
  517. red_black_node_t * rbtree_maximum(red_black_tree_t * tree)  
  518. {  
  519.     if (!(tree->root))  
  520.         return NULL;  
  521.     /* Return the rightmost leaf in the tree */  
  522.     return rbnode_maximum(tree->root);  
  523. }  
  524. /* Return a pointer to the node containing the given object */  
  525. red_black_node_t * rbtree_find(red_black_tree_t * tree, void * object)  
  526. {  
  527.     red_black_node_t * cur_node = tree->root;  
  528.     int comp_result;  
  529.     while (cur_node) {  
  530.         /* In case of equality, we can return the current node. */  
  531.         if ((comp_result = (*(tree->comp))(object, cur_node->object)) == 0)  
  532.             return cur_node;  
  533.         /* Go down to the left or right child. */  
  534.         cur_node = (comp_result > 0) ? cur_node->left : cur_node->right;  
  535.     }  
  536.     /* If we reached here, the object is not found in the tree */  
  537.     return NULL;  
  538. }  
  539. /* Left-rotate the sub-tree spanned by the given node: 
  540.  * 
  541.  *          |          RoateRight(y)            | 
  542.  *          y         -------------->           x 
  543.  *        /   /                               /   /       . 
  544.  *       x     T3       RoatateLeft(x)       T1    y      . 
  545.  *     /   /          <--------------            /   /    . 
  546.  *    T1    T2                                  T2    T3 
  547.  */  
  548. void rbtree_rotate_left(red_black_tree_t * tree, red_black_node_t * x_node)  
  549. {  
  550.     /* Get the right child of the node */  
  551.     red_black_node_t * y_node = x_node->right;  
  552.     /* Change its left subtree (T2) to x's right subtree */  
  553.     x_node->right = y_node->left;  
  554.     /* Link T2 to its new parent x */  
  555.     if (y_node->left != NULL)  
  556.         y_node->left->parent = x_node;  
  557.     /* Assign x's parent to be y's parent */  
  558.     y_node->parent = x_node->parent;  
  559.     if (!(x_node->parent)) {  
  560.         /* Make y the new tree root */  
  561.         tree->root = y_node;  
  562.     } else  {  
  563.         /* Assign a pointer to y from x's parent */  
  564.         if (x_node == x_node->parent->left) {  
  565.             x_node->parent->left = y_node;  
  566.         }  else {  
  567.             x_node->parent->right = y_node;  
  568.         }  
  569.     }  
  570.     /* Assign x to be y's left child */  
  571.     y_node->left = x_node;  
  572.     x_node->parent = y_node;  
  573. }  
  574. /* Right-rotate the sub-tree spanned by the given node */  
  575. void rbtree_rotate_right(red_black_tree_t * tree, red_black_node_t * y_node)  
  576. {  
  577.     /* Get the left child of the node */  
  578.     red_black_node_t * x_node = y_node->left;  
  579.     /* Change its right subtree (T2) to y's left subtree */  
  580.     y_node->left = x_node->right;  
  581.     /* Link T2 to its new parent y */  
  582.     if (x_node->right != NULL)  
  583.     x_node->right->parent = y_node;  
  584.     /* Assign y's parent to be x's parent */  
  585.     x_node->parent = y_node->parent;  
  586.     if (!(y_node->parent)) {  
  587.         /* Make x the new tree root */  
  588.         tree->root = x_node;  
  589.     } else  {  
  590.         /* Assign a pointer to x from y's parent */  
  591.         if (y_node == y_node->parent->left) {  
  592.             y_node->parent->left = x_node;  
  593.         } else {  
  594.             y_node->parent->right = x_node;  
  595.         }  
  596.     }  
  597.     /* Assign y to be x's right child */  
  598.     x_node->right = y_node;  
  599.     y_node->parent = x_node;  
  600. }  
  601. /* Fix-up the tree so it maintains the red-black properties after insertion */  
  602. void rbtree_insert_fixup(red_black_tree_t * tree, red_black_node_t * node)  
  603. {  
  604.     /* Fix the red-black propreties: we may have inserted a red leaf as the  
  605.      * child of a red parent - so we have to fix the coloring of the parent  
  606.      * recursively. 
  607.      */  
  608.     red_black_node_t * curr_node = node;  
  609.     red_black_node_t * grandparent;  
  610.     red_black_node_t *uncle;  
  611.     assert(node && node->color == rbcRed);  
  612.     
  613.     while (curr_node != tree->root && curr_node->parent->color == rbcRed) {  
  614.         /* Get a pointer to the current node's grandparent (notice the root is  
  615.          * always black, so the red parent must have a parent). 
  616.          */  
  617.         grandparent = curr_node->parent->parent;  
  618.           
  619.         if (curr_node->parent == grandparent->left) {  
  620.             /* If the red parent is a left child, the uncle is the right child of  
  621.              * the grandparent. 
  622.              */  
  623.             uncle = grandparent->right;  
  624.             if (uncle && uncle->color == rbcRed) {  
  625.                 /* If both parent and uncle are red, color them black and color the  
  626.                  * grandparent red. 
  627.                  * In case of a NULL uncle, we treat it as a black node. 
  628.                  */  
  629.                 curr_node->parent->color = rbcBlack;  
  630.                 uncle->color = rbcBlack;  
  631.                 grandparent->color = rbcRed;  
  632.                 /* Move to the grandparent */  
  633.                 curr_node = grandparent;  
  634.             } else {  
  635.                 /* Make sure the current node is a right child. If not, left-rotate  
  636.                  * the parent's sub-tree so the parent becomes the right child of the  
  637.                  * current node (see _rotate_left). 
  638.                  */  
  639.                 if (curr_node == curr_node->parent->right) {  
  640.                     curr_node = curr_node->parent;  
  641.                     rbtree_rotate_left(tree, curr_node);  
  642.                 }  
  643.                 /* Color the parent black and the grandparent red */  
  644.                 curr_node->parent->color = rbcBlack;  
  645.                 grandparent->color = rbcRed;  
  646.                 /* Right-rotate the grandparent's sub-tree */  
  647.                 rbtree_rotate_right(tree, grandparent);  
  648.             }  
  649.         } else {  
  650.             /* If the red parent is a right child, the uncle is the left child of  
  651.              * the grandparent. 
  652.              */  
  653.             uncle = grandparent->left;  
  654.             if (uncle && uncle->color == rbcRed) {  
  655.                 /* If both parent and uncle are red, color them black and color the  
  656.                  * grandparent red. 
  657.                  * In case of a NULL uncle, we treat it as a black node. 
  658.                  */  
  659.                 curr_node->parent->color = rbcBlack;  
  660.                 uncle->color = rbcBlack;  
  661.                 grandparent->color = rbcRed;  
  662.                 /* Move to the grandparent */  
  663.                 curr_node = grandparent;  
  664.             } else {  
  665.                 /* Make sure the current node is a left child. If not, right-rotate  
  666.                  * the parent's sub-tree so the parent becomes the left child of the  
  667.                  * current node. 
  668.                  */  
  669.                 if (curr_node == curr_node->parent->left) {  
  670.                     curr_node = curr_node->parent;  
  671.                     rbtree_rotate_right(tree, curr_node);  
  672.                 }  
  673.                 /* Color the parent black and the grandparent red */  
  674.                 curr_node->parent->color = rbcBlack;  
  675.                 grandparent->color = rbcRed;  
  676.                 /* Left-rotate the grandparent's sub-tree */  
  677.                 rbtree_rotate_left(tree, grandparent);  
  678.             }  
  679.         }  
  680.     }  
  681.     /* Make sure that the root is black */  
  682.     tree->root->color = rbcBlack;  
  683. }  
  684. void rbtree_remove_fixup(red_black_tree_t * tree, red_black_node_t * node)  
  685. {  
  686.     red_black_node_t * curr_node = node;  
  687.     red_black_node_t * sibling;  
  688.     while (curr_node != tree->root && curr_node->color == rbcBlack) {  
  689.         /* Get a pointer to the current node's sibling (notice that the node's  
  690.          * parent must exist, since the node is not the root). 
  691.          */  
  692.         if (curr_node == curr_node->parent->left) {  
  693.             /* If the current node is a left child, its sibling is the right  
  694.              * child of the parent. 
  695.              */  
  696.             sibling = curr_node->parent->right;  
  697.         
  698.             /* Check the sibling's color. Notice that NULL nodes are treated 
  699.              * as if they are colored black. 
  700.              */  
  701.             if (sibling && sibling->color == rbcRed) {  
  702.                 /* In case the sibling is red, color it black and rotate. 
  703.                  * Then color the parent red (and the grandparent is now black). 
  704.                  */  
  705.                 sibling->color = rbcBlack;  
  706.                 curr_node->parent->color = rbcRed;  
  707.                 rbtree_rotate_left(tree, curr_node->parent);  
  708.                 sibling = curr_node->parent->right;  
  709.             }  
  710.         
  711.             if (sibling &&   
  712.                 (!(sibling->left) || sibling->left->color == rbcBlack) &&   
  713.                 (!(sibling->right) || sibling->right->color == rbcBlack))  
  714.             {  
  715.                 /* If the sibling has two black children, color it red */  
  716.                 sibling->color = rbcRed;  
  717.                 if (curr_node->parent->color == rbcRed) {  
  718.                     /* If the parent is red, we can safely color it black and terminate 
  719.                      * the fix-up process. 
  720.                      */  
  721.                     curr_node->parent->color = rbcBlack;  
  722.                     curr_node = tree->root;      /* In order to stop the while loop */  
  723.                 } else {  
  724.                     /* The black depth of the entire sub-tree rooted at the parent is  
  725.                      * now too small - fix it up recursively. 
  726.                      */  
  727.                     curr_node = curr_node->parent;  
  728.                 }  
  729.             } else {  
  730.                 if (!sibling) {  
  731.                     /* Take special care of the case of a NULL sibling */  
  732.                     if (curr_node->parent->color == rbcRed) {  
  733.                         curr_node->parent->color = rbcBlack;  
  734.                         curr_node = tree->root;    /* In order to stop the while loop */  
  735.                     } else {  
  736.                         curr_node = curr_node->parent;  
  737.                     }  
  738.                 } else {  
  739.                     /* In this case, at least one of the sibling's children is red.  
  740.                      * It is therfore obvious that the sibling itself is black. 
  741.                      */  
  742.                     if (sibling->right && sibling->right->color == rbcRed) {  
  743.                         /* If the right child of the sibling is red, color it black and 
  744.                          * rotate around the current parent. 
  745.                          */  
  746.                         sibling->right->color = rbcBlack;  
  747.                         rbtree_rotate_left(tree, curr_node->parent);  
  748.                     } else {  
  749.                         /* If the left child of the sibling is red, rotate around the  
  750.                          * sibling, then rotate around the new sibling of our current 
  751.                          * node. 
  752.                          */  
  753.                         rbtree_rotate_right(tree, sibling);  
  754.                         sibling = curr_node->parent->right;  
  755.                         rbtree_rotate_left(tree, sibling);  
  756.                     }  
  757.                     /* It is now safe to color the parent black and to terminate the  
  758.                      * fix-up process. 
  759.                      */  
  760.                     if (curr_node->parent->parent)  
  761.                         curr_node->parent->parent->color = curr_node->parent->color;  
  762.                     curr_node->parent->color = rbcBlack;  
  763.                     curr_node = tree->root;      /* In order to stop the while loop */  
  764.                 }  
  765.             }  
  766.         } else {  
  767.             /* If the current node is a right child, its sibling is the left  
  768.              * child of the parent. 
  769.              */  
  770.             sibling = curr_node->parent->left;  
  771.             /* Check the sibling's color. Notice that NULL nodes are treated 
  772.              * as if they are colored black. 
  773.              */  
  774.             if (sibling && sibling->color == rbcRed) {  
  775.                 /* In case the sibling is red, color it black and rotate. 
  776.                  * Then color the parent red (and the grandparent is now black). 
  777.                  */  
  778.                 sibling->color = rbcBlack;  
  779.                 curr_node->parent->color = rbcRed;  
  780.                 rbtree_rotate_right(tree, curr_node->parent);  
  781.                 sibling = curr_node->parent->left;  
  782.             }  
  783.             if (sibling &&  
  784.                 (!(sibling->left) || sibling->left->color == rbcBlack) &&   
  785.                 (!(sibling->right) || sibling->right->color == rbcBlack))  
  786.             {  
  787.                 /* If the sibling has two black children, color it red */  
  788.                 sibling->color = rbcRed;  
  789.                 if (curr_node->parent->color == rbcRed) {  
  790.                     /* If the parent is red, we can safely color it black and terminate 
  791.                      * the fix-up process. 
  792.                      */  
  793.                     curr_node->parent->color = rbcBlack;  
  794.                     curr_node = tree->root;      /* In order to stop the while loop */  
  795.                 } else {  
  796.                     /* The black depth of the entire sub-tree rooted at the parent is  
  797.                      * now too small - fix it up recursively. 
  798.                      */  
  799.                     curr_node = curr_node->parent;  
  800.                 }  
  801.             } else {  
  802.                 if (!sibling) {  
  803.                     /* Take special care of the case of a NULL sibling */  
  804.                     if (curr_node->parent->color == rbcRed) {  
  805.                         curr_node->parent->color = rbcBlack;  
  806.                         curr_node = tree->root;    /* In order to stop the while loop */  
  807.                     } else {  
  808.                         curr_node = curr_node->parent;  
  809.                     }  
  810.                 } else {  
  811.                     /* In this case, at least one of the sibling's children is red.  
  812.                      * It is therfore obvious that the sibling itself is black. 
  813.                      */  
  814.                     if (sibling->left && sibling->left->color == rbcRed) {  
  815.                         /* If the left child of the sibling is red, color it black and 
  816.                          * rotate around the current parent 
  817.                          */  
  818.                         sibling->left->color = rbcBlack;  
  819.                         rbtree_rotate_right(tree, curr_node->parent);  
  820.                     } else {  
  821.                         /* If the right child of the sibling is red, rotate around the  
  822.                          * sibling, then rotate around the new sibling of our current  
  823.                          * node 
  824.                          */  
  825.                         rbtree_rotate_left(tree, sibling);  
  826.                         sibling = curr_node->parent->left;  
  827.                         rbtree_rotate_right(tree, sibling);  
  828.                     }  
  829.                     /* It is now safe to color the parent black and to terminate the  
  830.                      * fix-up process. 
  831.                      */  
  832.                     if (curr_node->parent->parent)  
  833.                         curr_node->parent->parent->color = curr_node->parent->color;  
  834.                     curr_node->parent->color = rbcBlack;  
  835.                     curr_node = tree->root;       /* In order to stop the while loop */  
  836.                 }  
  837.             }  
  838.         }  
  839.     }  
  840.     /* The root can always be colored black */  
  841.     curr_node->color = rbcBlack;  
  842. }  
  843. /* Traverse a red-black tree */  
  844. void rbtree_traverse(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param)  
  845. {  
  846.     rbnode_traverse(tree->root, op, param);  
  847. }  
  848. /* Right-first traverse a red-black tree */  
  849. void rbtree_traverse_right(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param)  
  850. {  
  851.     rbnode_traverse_right(tree->root, op, param);  
  852. }  

---------------------------

  1. //   
  2. // rbtree_test.c   
  3. // by cheungmine   
  4. //   
  5. #include <stdio.h>   
  6. #include <stdlib.h>   
  7. #include <assert.h>   
  8. // RBTREE_SUPPORTS_MULTI_OBJECTS 在下面的文件中被定义,如果不想支持多图,注释掉它   
  9. #include "red_black_tree.h"   
  10.   
  11. /*! 
  12.  */  
  13. int cmp_int(int a, int b)  
  14. {  
  15.   return (a > b) ? -1 : ((a == b) ? 0 : 1);  
  16. }  
  17. /*! 
  18.  */  
  19. void my_print(int value)  
  20. {  
  21.   printf("%d ", value);  
  22. }  
  23. #if !defined(RBTREE_SUPPORTS_MULTI_OBJECTS)   
  24. void test_rbtree_insert_repeat()  
  25. {  
  26.     int i, n;  
  27.       
  28.     red_black_tree_t  tree;  
  29.     red_black_node_t *node, *node2;  
  30.     n = 20;  
  31.     rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int);  
  32.     for (i=0; i<n; i++){  
  33.       rbtree_insert(&tree, (void*) i);  
  34.     }  
  35.     node = rbtree_find(&tree, (void*) 5);  
  36.     assert(node);  
  37.     node2 = rbtree_insert(&tree, (void*) 5);  
  38.     assert(node2);  
  39.     assert(node!=node2);  
  40.     node = rbtree_find(&tree, (void*) 10);  
  41.     assert(node);  
  42.     node2 = rbtree_insert(&tree, (void*) 10);  
  43.     assert(node2);  
  44.     assert(node!=node2);  
  45.     printf("n = %d, d = %d/n", n, rbtree_depth(&tree));  
  46.     rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print);  
  47.     printf("/n");  
  48.     rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print);  
  49.     printf("/n");  
  50.     rbtree_clean(&tree);  
  51. }  
  52. #endif   
  53. void test_rbtree_insert_unique()  
  54. {  
  55.     int i, n;  
  56.       
  57.     red_black_tree_t  tree;  
  58.     red_black_node_t *node, *node2;  
  59.     n = 20;  
  60.     rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int);  
  61.     for (i=0; i<n; i++){  
  62.       rbtree_insert_unique(&tree, (void*) i);  
  63.     }  
  64.     node = rbtree_find(&tree, (void*) 5);  
  65.     assert(node);  
  66.     node2 = rbtree_insert_unique(&tree, (void*) 5);  
  67.     assert(node2);  
  68.     assert(node==node2);  
  69.     node = rbtree_find(&tree, (void*) 10);  
  70.     assert(node);  
  71.     node2 = rbtree_insert_unique(&tree, (void*) 10);  
  72.     assert(node2);  
  73.     assert(node==node2);  
  74.     printf("n = %d, d = %d/n", n, rbtree_depth(&tree));  
  75.     rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print, 0);  
  76.     printf("/n");  
  77.     rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print, 0);  
  78.     printf("/n");  
  79.     rbtree_clean(&tree);  
  80. }  
  81. #ifdef RBTREE_SUPPORTS_MULTI_OBJECTS   
  82. typedef struct _MYOBJECT  
  83. {  
  84.     struct _MYOBJECT *__next_object;  
  85.     int  data;  
  86. }MYOBJECT;  
  87. int cmp_int_multimap(MYOBJECT *a, MYOBJECT *b)  
  88. {  
  89.   return (a->data > b->data) ? -1 : ((a->data == b->data) ? 0 : 1);  
  90. }  
  91. /*! 
  92.  */  
  93. void my_print_multimap(MYOBJECT *obj)  
  94. {  
  95.     while (obj) {  
  96.         printf("%d ", obj->data);  
  97.         obj = obj->__next_object;  
  98.     }  
  99. }  
  100. void test_rbtree_insert_multimap()  
  101. {  
  102.     int i, n;  
  103.     MYOBJECT *obj;  
  104.     MYOBJECT **objects;  
  105.     red_black_tree_t  tree;  
  106.     red_black_node_t *node;  
  107.     n = 20;  
  108.     rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int_multimap);  
  109.     objects = (MYOBJECT**) calloc(n, sizeof(MYOBJECT*));  
  110.     for (i=0; i<n; i++){  
  111.         obj = (MYOBJECT*) malloc(sizeof(MYOBJECT));  
  112.         objects[i] = obj;  
  113.         obj->__next_object = 0;  // MUST be NULL   
  114.         obj->data = i;  
  115.           
  116.         rbtree_insert(&tree, (void*) obj);  
  117.     }  
  118.     rbtree_insert(&tree, (void*) objects[5]);  
  119.     obj = (MYOBJECT*) malloc(sizeof(MYOBJECT));  
  120.     obj->__next_object = 0;  // MUST be NULL   
  121.     obj->data = 5;  
  122.     rbtree_insert(&tree, (void*) obj);  
  123.               
  124.     printf("n = %d, d = %d/n", n, rbtree_depth(&tree));  
  125.     printf("(");  
  126.     node = rbtree_find(&tree, (void*) objects[5]);  
  127.     if (node){  
  128.         MYOBJECT *obj = node->object;  
  129.         while (obj) {  
  130.             printf("%d ", obj->data);  
  131.             obj = obj->__next_object;  
  132.         }  
  133.     }  
  134.     printf(")/n");  
  135.     rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print_multimap, 0);  
  136.     printf("/n");  
  137.     rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print_multimap, 0);  
  138.     printf("/n");  
  139.     rbtree_clean(&tree);  
  140.     for (i=0; i<n; i++){  
  141.         free(objects[i]);  
  142.     }  
  143.     free(objects);  
  144.     free(obj);  
  145. }  
  146. #endif // RBTREE_SUPPORTS_MULTI_OBJECTS   
  147. int main(int argc, char * argv[])  
  148. {  
  149. #if !defined(RBTREE_SUPPORTS_MULTI_OBJECTS)   
  150.     test_rbtree_insert_repeat();  
  151. #endif   
  152.     test_rbtree_insert_unique();  
  153.     test_rbtree_insert_multimap();  
  154.     return 0;  
  155. }  

任何人使用此代码必须遵守原作者的协议。

相关内容