红黑树与C实现算法

来源:互联网 发布:软件信息服务业 编辑:程序博客网 时间:2024/05/13 19:51


红黑树与C实现算法 


cheungmine


本文全部内容摘自互联网,作者根据需要做了修改和补充,最主要的是提供了对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):


view plaincopy to clipboardprint?
/******************************************************************************  
* red_black_tree.h                                                            *  
* Download From:                                                              *  
*    http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03/code/rbtree/   *  
* Last Edited by:                                                             *  
*    cheungmine                                                               *  
* 2010-8                                                                      *  
* Container class for a red-black tree: A binary tree that satisfies the      *  
* following properties:                                                       *  
* 1. Each node has a color, which is either red or black.                     *  
* 2. A red node cannot have a red parent.                                     *  
* 3. The number of black nodes from every path from the tree root to a leaf   *  
*    is the same for all tree leaves (it is called the 'black depth' of the   *  
*    tree).                                                                   *  
* Due to propeties 2-3, the depth of a red-black tree containing n nodes      *  
* is bounded by 2*log_2(n).                                                   *            
*                                                                             *  
* The red_black_tree_t template requires two template parmeters:              *  
* - The contained TYPE class represents the objects stored in the tree.       *  
*   It has to support the copy constructor and the assignment operator        *  
*   (operator=).                                                              *  
*                                                                             *  
* - pfcbRBTreeCompFunc is a functor used to define the order of objects of    *  
*   class TYPE:                                                               *  
*   This class has to support an operator() that recieves two objects from    *  
*   the TYPE class and returns a negative, zero or a positive integer,        *  
*   depending on the comparison result.                                       *  
******************************************************************************/  
#ifndef RED_BLACK_TREE_H   
#define RED_BLACK_TREE_H   
/*!  
 * Define RBTREE_SUPPORTS_MULTI_OBJECTS for supporting mapset (multi-key-map)  
 * if RBTREE_SUPPORTS_MULTI_OBJECTS defined, object must inherit from struct  
 * rbtree_object_base. That means the first member of object must be a struct  
 * pointer to next possible object if it has.  
 *  
 * #define  RBTREE_SUPPORTS_MULTI_OBJECTS  
 */  
#define  RBTREE_SUPPORTS_MULTI_OBJECTS   
#ifdef RBTREE_SUPPORTS_MULTI_OBJECTS   
    typedef struct _rbtree_object_base {   
        struct _rbtree_object_base *__next_object;   
    }rbtree_object_base;   
#endif   
/*! Color enumeration for nodes of red-black tree */  
typedef enum _red_black_color_enum    
{   
    rbcRed,    
    rbcBlack   
} red_black_color_enum;   
/*! Representation of a node in a red-black tree */  
typedef struct _red_black_node_t {   
    void                     * object;       /* the stored object user defined */  
    red_black_color_enum       color;        /* the color of the node */  
    struct _red_black_node_t * parent;       /* points to the parent node */  
    struct _red_black_node_t * right;        /* points to the right child */  
    struct _red_black_node_t * left;         /* points to the left child */  
} red_black_node_t;   
/*! Callback function prototype for comparing objects */  
typedef int (pfcbRBTreeCompFunc)(void *object1, void *object2);   
/*! Callback function prototype for traverse objects */  
typedef void(pfcbRBTreeOperFunc)(void *object,  void *param);   
     
/*! Construct of a red-black tree node  
 *  param object The object stored in the node  
 *  param color The color of the node  
 */  
extern red_black_node_t * rbnode_construct(void * object, red_black_color_enum color);   
/*! Recursive destructor for the entire sub-tree */  
extern void rbnode_destruct(red_black_node_t * node);   
/*! Calculate the depth of the sub-tree spanned by the given node  
 *  param node The sub-tree root  
 *  return The sub-tree depth  
 */  
extern int rbnode_depth(red_black_node_t * node);   
/*! Get the leftmost node in the sub-tree spanned by the given node  
 *  param node The sub-tree root  
 *  return The sub-tree minimum  
 */  
extern red_black_node_t * rbnode_minimum(red_black_node_t * node);   
/*! Get the rightmost node in the sub-tree spanned by the given node  
 *  param node The sub-tree root  
 *  return The sub-tree maximum  
 */  
extern red_black_node_t * rbnode_maximum(red_black_node_t * node);   
/*! Replace the object */  
extern void rbnode_replace(red_black_node_t * node, void * object);   
/*! Get the next node in the tree (according to the tree order)  
 *  param node The current node  
 *  return The successor node, or NULL if node is the tree maximum  
 */  
extern red_black_node_t * rbnode_successor(red_black_node_t * node);   
/*! Get the previous node in the tree (according to the tree order)  
 *  param node The current node  
 *  return The predecessor node, or NULL if node is the tree minimum  
 */  
extern red_black_node_t * rbnode_predecessor(red_black_node_t * node);   
/*! Duplicate the entire sub-tree rooted at the given node  
 *  param node The sub-tree root  
 *  return A pointer to the duplicated sub-tree root  
 */  
extern red_black_node_t * rbnode_duplicate(red_black_node_t * node);   
/*! Traverse a red-black sub-tree left first  
 *  param node The sub-tree root  
 *  param op The operation to perform on each object in the sub-tree  
 */  
extern void rbnode_traverse(red_black_node_t *node, pfcbRBTreeOperFunc *opFunc, void *param);   
/*! Traverse a red-black sub-tree right first  
 */  
extern void rbnode_traverse_right(red_black_node_t *node, pfcbRBTreeOperFunc *opFunc, void*param);   
/*! Representation of a red-black tree */  
typedef struct _red_black_tree_t {   
    red_black_node_t   * root;                /* pointer to the tree root */  
    int                  iSize;               /* number of objects stored */  
    pfcbRBTreeCompFunc * comp;                /* compare function */  
} red_black_tree_t;   
/*! Initialize a red-black tree with a comparision function  
 *  param tree The tree  
 *  param comp The comparision function  
 */  
void rbtree_init(red_black_tree_t * tree, pfcbRBTreeCompFunc * comp);   
/*! Construct a red-black tree with a comparison object  
 *  param comp A pointer to the comparison object to be used by the tree  
 *  return The newly constructed  tree  
 */  
red_black_tree_t * rbtree_construct(pfcbRBTreeCompFunc * comp);   
/*! Clean a red-black tree [takes O(n) operations]  
 *  param tree The tree  
 */  
extern void rbtree_clean(red_black_tree_t * tree);   
/*! Destruct a red-black tree  
 *  param tree The tree  
 */  
extern void rbtree_destruct(red_black_tree_t * tree);   
/*! Get the size of the tree [takes O(1) operations]  
 *  param tree The tree  
 *  return The number of objects stored in the tree  
 */  
extern int rbtree_size(red_black_tree_t * tree);   
/*! Get the depth of the tree [takes O(n) operations]  
 *  param tree The tree  
 *  return The length of the longest path from the root to a leaf node  
 */  
extern int rbtree_depth(red_black_tree_t * tree);   
/*! Check whether the tree contains an object [takes O(log n) operations]  
 *  param tree The tree  
 *  param object The query object  
 *  return (true) if an equal object is found in the tree, otherwise (false)  
 */  
extern int rbtree_contains(red_black_tree_t * tree, void * object);   
/*! Insert an object to the tree [takes O(log n) operations]  
 *  param tree The tree  
 *  param object The object to be inserted  
 *  return the inserted object node  
 */  
extern red_black_node_t * rbtree_insert(red_black_tree_t * tree, void * object);   
/*! Insert an unique object to the tree */  
extern red_black_node_t * rbtree_insert_unique(red_black_tree_t * tree, void * object);   
/*! Insert a new object to the tree as the a successor of a given node  
 *  param tree The tree  
 *  return The new node  
 */  
extern red_black_node_t * insert_successor_at(red_black_tree_t * tree,   
                                            red_black_node_t * at_node,   
                                            void * object);   
/*! Insert a new object to the tree as the a predecessor of a given node  
 *  param tree The tree  
 *  return The new node  
 */  
extern red_black_node_t * insert_predecessor_at(red_black_tree_t * tree,   
                                              red_black_node_t * at_node,   
                                              void * object);   
/*! Remove an object from the tree [takes O(log n) operations]  
 *  param tree The tree  
 *  param object The object to be removed  
 *  pre The object should be contained in the tree  
 */  
extern void rbtree_remove(red_black_tree_t * tree, void * object);   
/*! Get a handle to the tree minimum [takes O(log n) operations]  
 *  param tree The tree  
 *  return the minimal object in the tree, or a NULL if the tree is empty  
 */  
extern red_black_node_t * rbtree_minimum(red_black_tree_t * tree);   
/*! Get a handle to the tree maximum [takes O(log n) operations]  
 *  param tree The tree  
 *  return the maximal object in the tree, or a NULL if the tree is empty  
 */  
extern red_black_node_t * rbtree_maximum(red_black_tree_t * tree);   
/*! Get the next node in the tree (according to the tree order)  
 * [takes O(log n) operations at worst-case, but only O(1) amortized]  
 *  param tree The tree  
 *  param node The current object  
 *  return The successor node, or a NULL, if we are at the tree maximum  
 */  
extern red_black_node_t * rbtree_successor(red_black_tree_t * tree,   
                                           red_black_node_t * node);   
/*! Get the previous node in the tree (according to the tree order)  
 * [takes O(log n) operations at worst-case, but only O(1) amortized]  
 *  param tree The tree  
 *  param node The current object  
 *  return The predecessor node, or a NULL, if we are at the tree minimum  
 */  
extern red_black_node_t * rbtree_predecessor(red_black_tree_t * tree,   
                                             red_black_node_t * node);   
/*! Find a node that contains the given object  
 *  param tree The tree  
 *  param object The desired object  
 *  return A node that contains the given object, or NULL if no such object  
 * is found in the tree  
 */  
extern red_black_node_t * rbtree_find(red_black_tree_t * tree, void * object);   
/*! Remove the object stored in the given tree node   
 *  param tree The tree  
 *  param node The node storing the object to be removed from the tree  
 */  
extern void rbtree_remove_at(red_black_tree_t * tree, red_black_node_t * node);   
/*! Left-rotate the sub-tree spanned by the given node  
 *  param tree The tree  
 *  param node The sub-tree root  
 */  
extern void rbtree_rotate_left(red_black_tree_t * tree, red_black_node_t * node);   
/*! Right-rotate the sub-tree spanned by the given node  
 *  param tree The tree  
 *  param node The sub-tree root  
 */  
extern void rbtree_rotate_right(red_black_tree_t * tree, red_black_node_t * node);   
/*!  
 * Fix-up the red-black tree properties after an insertion operation  
 *  param tree The tree  
 *  param node The node that has just been inserted to the tree  
 *  pre The color of node must be red  
 */  
extern void rbtree_insert_fixup(red_black_tree_t * tree, red_black_node_t * node);   
/*! Fix-up the red-black tree properties after a removal operation  
 *  param tree The tree  
 *  param node The child of the node that has just been removed from the tree  
 */  
extern void rbtree_remove_fixup(red_black_tree_t * tree, red_black_node_t * node);   
/*! Traverse a red-black tree left first  
 *  param tree The tree  
 *  param op The operation to perform on every object of the tree (according to  
 * the tree order)  
 */  
extern void rbtree_traverse(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param);   
#define rbtree_traverse_left rbtree_traverse   
/*! Traverse a red-black tree right first */  
extern void rbtree_traverse_right(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param);   
#endif /* RED_BLACK_TREE_H */  
/******************************************************************************
* red_black_tree.h                                                            *
* Download From:                                                              *
*    http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03/code/rbtree/   *
* Last Edited by:                                                             *
*    cheungmine                                                               *
* 2010-8                                                                      *
* Container class for a red-black tree: A binary tree that satisfies the      *
* following properties:                                                       *
* 1. Each node has a color, which is either red or black.                     *
* 2. A red node cannot have a red parent.                                     *
* 3. The number of black nodes from every path from the tree root to a leaf   *
*    is the same for all tree leaves (it is called the 'black depth' of the   *
*    tree).                                                                   *
* Due to propeties 2-3, the depth of a red-black tree containing n nodes      *
* is bounded by 2*log_2(n).                                                   *          
*                                                                             *
* The red_black_tree_t template requires two template parmeters:              *
* - The contained TYPE class represents the objects stored in the tree.       *
*   It has to support the copy constructor and the assignment operator        *
*   (operator=).                                                              *
*                                                                             *
* - pfcbRBTreeCompFunc is a functor used to define the order of objects of    *
*   class TYPE:                                                               *
*   This class has to support an operator() that recieves two objects from    *
*   the TYPE class and returns a negative, zero or a positive integer,        *
*   depending on the comparison result.                                       *
******************************************************************************/
#ifndef RED_BLACK_TREE_H
#define RED_BLACK_TREE_H
/*!
 * Define RBTREE_SUPPORTS_MULTI_OBJECTS for supporting mapset (multi-key-map)
 * if RBTREE_SUPPORTS_MULTI_OBJECTS defined, object must inherit from struct
 * rbtree_object_base. That means the first member of object must be a struct
 * pointer to next possible object if it has.
 *
 * #define  RBTREE_SUPPORTS_MULTI_OBJECTS
 */
#define  RBTREE_SUPPORTS_MULTI_OBJECTS
#ifdef RBTREE_SUPPORTS_MULTI_OBJECTS
    typedef struct _rbtree_object_base {
        struct _rbtree_object_base *__next_object;
    }rbtree_object_base;
#endif
/*! Color enumeration for nodes of red-black tree */
typedef enum _red_black_color_enum 
{
    rbcRed, 
    rbcBlack
} red_black_color_enum;
/*! Representation of a node in a red-black tree */
typedef struct _red_black_node_t {
    void                     * object;       /* the stored object user defined */
    red_black_color_enum       color;        /* the color of the node */
    struct _red_black_node_t * parent;       /* points to the parent node */
    struct _red_black_node_t * right;        /* points to the right child */
    struct _red_black_node_t * left;         /* points to the left child */
} red_black_node_t;
/*! Callback function prototype for comparing objects */
typedef int (pfcbRBTreeCompFunc)(void *object1, void *object2);
/*! Callback function prototype for traverse objects */
typedef void(pfcbRBTreeOperFunc)(void *object,  void *param);
  
/*! Construct of a red-black tree node
 *  param object The object stored in the node
 *  param color The color of the node
 */
extern red_black_node_t * rbnode_construct(void * object, red_black_color_enum color);
/*! Recursive destructor for the entire sub-tree */
extern void rbnode_destruct(red_black_node_t * node);
/*! Calculate the depth of the sub-tree spanned by the given node
 *  param node The sub-tree root
 *  return The sub-tree depth
 */
extern int rbnode_depth(red_black_node_t * node);
/*! Get the leftmost node in the sub-tree spanned by the given node
 *  param node The sub-tree root
 *  return The sub-tree minimum
 */
extern red_black_node_t * rbnode_minimum(red_black_node_t * node);
/*! Get the rightmost node in the sub-tree spanned by the given node
 *  param node The sub-tree root
 *  return The sub-tree maximum
 */
extern red_black_node_t * rbnode_maximum(red_black_node_t * node);
/*! Replace the object */
extern void rbnode_replace(red_black_node_t * node, void * object);
/*! Get the next node in the tree (according to the tree order)
 *  param node The current node
 *  return The successor node, or NULL if node is the tree maximum
 */
extern red_black_node_t * rbnode_successor(red_black_node_t * node);
/*! Get the previous node in the tree (according to the tree order)
 *  param node The current node
 *  return The predecessor node, or NULL if node is the tree minimum
 */
extern red_black_node_t * rbnode_predecessor(red_black_node_t * node);
/*! Duplicate the entire sub-tree rooted at the given node
 *  param node The sub-tree root
 *  return A pointer to the duplicated sub-tree root
 */
extern red_black_node_t * rbnode_duplicate(red_black_node_t * node);
/*! Traverse a red-black sub-tree left first
 *  param node The sub-tree root
 *  param op The operation to perform on each object in the sub-tree
 */
extern void rbnode_traverse(red_black_node_t *node, pfcbRBTreeOperFunc *opFunc, void *param);
/*! Traverse a red-black sub-tree right first
 */
extern void rbnode_traverse_right(red_black_node_t *node, pfcbRBTreeOperFunc *opFunc, void*param);
/*! Representation of a red-black tree */
typedef struct _red_black_tree_t {
    red_black_node_t   * root;                /* pointer to the tree root */
    int                  iSize;               /* number of objects stored */
    pfcbRBTreeCompFunc * comp;                /* compare function */
} red_black_tree_t;
/*! Initialize a red-black tree with a comparision function
 *  param tree The tree
 *  param comp The comparision function
 */
void rbtree_init(red_black_tree_t * tree, pfcbRBTreeCompFunc * comp);
/*! Construct a red-black tree with a comparison object
 *  param comp A pointer to the comparison object to be used by the tree
 *  return The newly constructed  tree
 */
red_black_tree_t * rbtree_construct(pfcbRBTreeCompFunc * comp);
/*! Clean a red-black tree [takes O(n) operations]
 *  param tree The tree
 */
extern void rbtree_clean(red_black_tree_t * tree);
/*! Destruct a red-black tree
 *  param tree The tree
 */
extern void rbtree_destruct(red_black_tree_t * tree);
/*! Get the size of the tree [takes O(1) operations]
 *  param tree The tree
 *  return The number of objects stored in the tree
 */
extern int rbtree_size(red_black_tree_t * tree);
/*! Get the depth of the tree [takes O(n) operations]
 *  param tree The tree
 *  return The length of the longest path from the root to a leaf node
 */
extern int rbtree_depth(red_black_tree_t * tree);
/*! Check whether the tree contains an object [takes O(log n) operations]
 *  param tree The tree
 *  param object The query object
 *  return (true) if an equal object is found in the tree, otherwise (false)
 */
extern int rbtree_contains(red_black_tree_t * tree, void * object);
/*! Insert an object to the tree [takes O(log n) operations]
 *  param tree The tree
 *  param object The object to be inserted
 *  return the inserted object node
 */
extern red_black_node_t * rbtree_insert(red_black_tree_t * tree, void * object);
/*! Insert an unique object to the tree */
extern red_black_node_t * rbtree_insert_unique(red_black_tree_t * tree, void * object);
/*! Insert a new object to the tree as the a successor of a given node
 *  param tree The tree
 *  return The new node
 */
extern red_black_node_t * insert_successor_at(red_black_tree_t * tree,
                                            red_black_node_t * at_node,
                                            void * object);
/*! Insert a new object to the tree as the a predecessor of a given node
 *  param tree The tree
 *  return The new node
 */
extern red_black_node_t * insert_predecessor_at(red_black_tree_t * tree,
                                              red_black_node_t * at_node,
                                              void * object);
/*! Remove an object from the tree [takes O(log n) operations]
 *  param tree The tree
 *  param object The object to be removed
 *  pre The object should be contained in the tree
 */
extern void rbtree_remove(red_black_tree_t * tree, void * object);
/*! Get a handle to the tree minimum [takes O(log n) operations]
 *  param tree The tree
 *  return the minimal object in the tree, or a NULL if the tree is empty
 */
extern red_black_node_t * rbtree_minimum(red_black_tree_t * tree);
/*! Get a handle to the tree maximum [takes O(log n) operations]
 *  param tree The tree
 *  return the maximal object in the tree, or a NULL if the tree is empty
 */
extern red_black_node_t * rbtree_maximum(red_black_tree_t * tree);
/*! Get the next node in the tree (according to the tree order)
 * [takes O(log n) operations at worst-case, but only O(1) amortized]
 *  param tree The tree
 *  param node The current object
 *  return The successor node, or a NULL, if we are at the tree maximum
 */
extern red_black_node_t * rbtree_successor(red_black_tree_t * tree,
                                           red_black_node_t * node);
/*! Get the previous node in the tree (according to the tree order)
 * [takes O(log n) operations at worst-case, but only O(1) amortized]
 *  param tree The tree
 *  param node The current object
 *  return The predecessor node, or a NULL, if we are at the tree minimum
 */
extern red_black_node_t * rbtree_predecessor(red_black_tree_t * tree,
                                             red_black_node_t * node);
/*! Find a node that contains the given object
 *  param tree The tree
 *  param object The desired object
 *  return A node that contains the given object, or NULL if no such object
 * is found in the tree
 */
extern red_black_node_t * rbtree_find(red_black_tree_t * tree, void * object);
/*! Remove the object stored in the given tree node 
 *  param tree The tree
 *  param node The node storing the object to be removed from the tree
 */
extern void rbtree_remove_at(red_black_tree_t * tree, red_black_node_t * node);
/*! Left-rotate the sub-tree spanned by the given node
 *  param tree The tree
 *  param node The sub-tree root
 */
extern void rbtree_rotate_left(red_black_tree_t * tree, red_black_node_t * node);
/*! Right-rotate the sub-tree spanned by the given node
 *  param tree The tree
 *  param node The sub-tree root
 */
extern void rbtree_rotate_right(red_black_tree_t * tree, red_black_node_t * node);
/*!
 * Fix-up the red-black tree properties after an insertion operation
 *  param tree The tree
 *  param node The node that has just been inserted to the tree
 *  pre The color of node must be red
 */
extern void rbtree_insert_fixup(red_black_tree_t * tree, red_black_node_t * node);
/*! Fix-up the red-black tree properties after a removal operation
 *  param tree The tree
 *  param node The child of the node that has just been removed from the tree
 */
extern void rbtree_remove_fixup(red_black_tree_t * tree, red_black_node_t * node);
/*! Traverse a red-black tree left first
 *  param tree The tree
 *  param op The operation to perform on every object of the tree (according to
 * the tree order)
 */
extern void rbtree_traverse(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param);
#define rbtree_traverse_left rbtree_traverse
/*! Traverse a red-black tree right first */
extern void rbtree_traverse_right(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param);
#endif /* RED_BLACK_TREE_H */
 


view plaincopy to clipboardprint?
01./******************************************************************************  
02.* red_black_tree.c                                                            *  
03.* Download From:                                                              *  
04.*    http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03/code/rbtree/   *  
05.* Last Edited by: cheungmine                                                  *  
06.******************************************************************************/  
07.#include <stdio.h>   
08.#include <stdlib.h>   
09.#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.}  
/******************************************************************************
* red_black_tree.c                                                            *
* Download From:                                                              *
*    http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03/code/rbtree/   *
* Last Edited by: cheungmine                                                  *
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "red_black_tree.h"
/*!
 * Operations on red_black_node_t struct
 */
/* Construct a red-black tree node */
red_black_node_t * rbnode_construct(void * object, red_black_color_enum color)
{
    red_black_node_t * node = (red_black_node_t *) malloc(sizeof(red_black_node_t));
    if (!node) {
        fprintf(stderr, "Not enough memory!\n");
        return NULL;
    }
    node->object = object;
    node->color = color;
    node->parent = node->right = node->left = NULL;
    return node;
}
/* Destructor of a red-black tree node */
void rbnode_destruct(red_black_node_t * node)
{
    if (!node) return;
    rbnode_destruct(node->right);
    rbnode_destruct(node->left);
    free(node);
}
/* Calculate the depth of the subtree spanned by a given node */
int rbnode_depth(red_black_node_t * node)
{
    /* Recursively calculate the depth of the left and right sub-trees */
    int  iRightDepth = (node->right) ? rbnode_depth(node->right) : 0;
    int  iLeftDepth = (node->left) ? rbnode_depth(node->left) : 0;
    /* Return the maximal child depth + 1 (the current node) */
    return ((iRightDepth > iLeftDepth) ? (iRightDepth + 1) : (iLeftDepth + 1));
}
/* Return the leftmost leaf in the tree */
red_black_node_t * rbnode_minimum(red_black_node_t * node)
{
    while (node->left)
        node = node->left;
    return node;
}
/* Return the rightmost leaf in the tree */
red_black_node_t * rbnode_maximum(red_black_node_t * node)
{
    while (node->right)
        node = node->right;
    return node;
}
/* Replace the object */
void rbnode_replace(red_black_node_t * node, void * object)
{
    /* Make sure the replacement does not violate the tree order */
    /* Replace the object at node */
    node->object = object;
}
        
/* Get the next node in the tree (according to the tree order) */
red_black_node_t * rbnode_successor(red_black_node_t * node)
{
    red_black_node_t * succ_node;
    if (node->right) {
        /* If there is a right child, the successor is the minimal object in 
         * the sub-tree spanned by this child.
         */
        succ_node = node->right;
        while (succ_node->left)
            succ_node = succ_node->left;
    } 
    else {
        /* Otherwise, go up the tree until reaching the parent from the left 
         * direction.
         */
        red_black_node_t * prev_node = node;
        succ_node = node->parent;
        while (succ_node && prev_node == succ_node->right) {
            prev_node = succ_node;
            succ_node = succ_node->parent;
        }
    }
    return (succ_node);
}
/* Get the previous node in the tree (according to the tree order) */
red_black_node_t * rbnode_predecessor(red_black_node_t * node)
{
    red_black_node_t * pred_node;
    if (node->left) {
        /* If there is a left child, the predecessor is the maximal object in 
         * the sub-tree spanned by this child.
         */
        pred_node = node->left;
        while (pred_node->right)
            pred_node = pred_node->right;
    } else {
        /* Otherwise, go up the tree until reaching the parent from the right 
         * direction.
         */
        red_black_node_t * prev_node = node;
        pred_node = node->parent;
        while (pred_node && prev_node == pred_node->left) {
            prev_node = pred_node;
            pred_node = pred_node->parent;
        }
    }
    return (pred_node);
}
/* Return a pointer to a duplication of the given node */
red_black_node_t * rbnode_duplicate(red_black_node_t * node)
{
    /* Create a node of the same color, containing the same object */
    red_black_node_t * dup_node = rbnode_construct(node->object, node->color);
    if (!dup_node) return NULL;
    /* Duplicate the children recursively */
    if (node->right) {
        dup_node->right = rbnode_duplicate (node->right);
        dup_node->right->parent = dup_node;
    } else {
        dup_node->right = NULL;
    }
    if (node->left) {
        dup_node->left = rbnode_duplicate(node->left);
        dup_node->left->parent = dup_node;
    } else {
        dup_node->left = NULL;
    }
    return dup_node;                      /* Return the duplicated node */
}
/* Traverse a red-black subtree */
void rbnode_traverse(red_black_node_t * node, pfcbRBTreeOperFunc * opFunc, void* param)
{
    if (!node) return;
    rbnode_traverse(node->left, opFunc, param);
    opFunc(node->object, param);
    rbnode_traverse(node->right, opFunc, param);
}
/* Right-first traverse a red-black subtree */
void rbnode_traverse_right(red_black_node_t * node, pfcbRBTreeOperFunc * opFunc, void* param)
{
    if (!node) return;
    rbnode_traverse_right(node->right, opFunc, param);
    opFunc(node->object, param);
    rbnode_traverse_right(node->left, opFunc, param);
}
/*
 * Operations on red_black_tree_t struct
 */
/* Intialize a tree */
void rbtree_init(red_black_tree_t * tree, pfcbRBTreeCompFunc * comp)
{
    tree->comp = comp;
    tree->iSize = 0;
    tree->root = NULL;
}
/* Construct a tree given a comparison function */
red_black_tree_t * rbtree_construct(pfcbRBTreeCompFunc * comp)
{
    red_black_tree_t * tree = (red_black_tree_t *) malloc(sizeof(red_black_tree_t));
    if (!tree) {
        fprintf(stderr, "Not enough memory!\n");
        return NULL;
    }
    rbtree_init(tree, comp);
    return tree;
}
/* Remove all objects from a black-red tree */
void rbtree_clean(red_black_tree_t * tree)
{
    if (tree->root)
        rbnode_destruct(tree->root);
    tree->root = NULL;
    tree->iSize = 0;
}
/* Destruct a red-black tree */
void rbtree_destruct(red_black_tree_t * tree)
{
    rbtree_clean(tree);
    free(tree);
}
/* Returns the size of the tree */
int rbtree_size(red_black_tree_t * tree)
{
    return tree->iSize;
}
/* Returns the depth of the tree */
int rbtree_depth(red_black_tree_t * tree)
{
    if (!(tree->root))
        return 0;
    return rbnode_depth(tree->root);
}
/* Check whether the tree contains an object */
int rbtree_contains(red_black_tree_t * tree, void * object)
{
    return (rbtree_find(tree, object) != NULL);
}
/* Insert an object to the tree */
red_black_node_t * rbtree_insert(red_black_tree_t * tree, void * object)
{
    int cmp;
    red_black_node_t * cur_node;
    red_black_node_t * new_node = NULL;
  
    if (!(tree->root)) {
        /* Assign a new root node. Notice that the root is always black */
        new_node = rbnode_construct(object, rbcBlack);
        if (!new_node) return NULL;
        tree->root = new_node;
        tree->iSize = 1;
        return new_node;
    }
    /* Find a place for the new object, and insert it as a red leaf */
    cur_node = tree->root;
    
    while (cur_node) {
        cmp = (*(tree->comp))(object, cur_node->object);
#ifdef RBTREE_SUPPORTS_MULTI_OBJECTS
        if (cmp==0) {
            if (cur_node->object != object)
                ((rbtree_object_base*)cur_node->object)->__next_object = (rbtree_object_base*)object;
            return cur_node;
        }
#endif
        /* Compare inserted object with the object stored in the current node */
        if (cmp > 0) {
            if (!(cur_node->left)) {
                /* Insert the new leaf as the left child of the current node */
                new_node = rbnode_construct(object, rbcRed);
                if (!new_node) return NULL;
                cur_node->left = new_node;
                new_node->parent = cur_node;
                cur_node = NULL;                /* terminate the while loop */
            } else {
                cur_node = cur_node->left;      /* Go to the left sub-tree */
            }
        } else {
            if (!(cur_node->right)) {
                /* Insert the new leaf as the right child of the current node */
                new_node = rbnode_construct(object, rbcRed);
                if (!new_node) return NULL;
                cur_node->right = new_node;
                new_node->parent = cur_node;
                cur_node = NULL;                /* terminate the while loop */
            } else {
                cur_node = cur_node->right;     /* Go to the right sub-tree */
            }
        }
    }
    /* Mark that a new node was added */
    tree->iSize++;
    /* Fix up the tree properties */
    rbtree_insert_fixup(tree, new_node);  
    return new_node;
}
/* Insert an unique object to the tree */
red_black_node_t * rbtree_insert_unique(red_black_tree_t * tree, void * object)
{
    int cmp;
    red_black_node_t * cur_node;
    red_black_node_t * new_node = NULL;
  
    if (!(tree->root)) {
        /* Assign a new root node. Notice that the root is always black */
        new_node = rbnode_construct(object, rbcBlack);
        if (!new_node) return NULL;
        tree->root = new_node;
        tree->iSize = 1;
        return new_node;
    }
    /* Find a place for the new object, and insert it as a red leaf */
    cur_node = tree->root;
    while (cur_node) {
        cmp = (*(tree->comp))(object, cur_node->object);
        if (cmp==0) {
            /* there already has an object with the same id as object to be inserted */
            return cur_node;
        }
        /* Compare inserted object with the object stored in the current node */
        if (cmp > 0) {
            if (!(cur_node->left)) {
                /* Insert the new leaf as the left child of the current node */
                new_node = rbnode_construct(object, rbcRed);
                if (!new_node) 
                    return NULL;
                cur_node->left = new_node;
                new_node->parent = cur_node;
                cur_node = NULL;                /* terminate the while loop */
            } else {
                cur_node = cur_node->left;      /* Go to the left sub-tree */
            }
        } else {
            if (!(cur_node->right)) {
                /* Insert the new leaf as the right child of the current node */
                new_node = rbnode_construct(object, rbcRed);
                if (!new_node) 
                    return NULL;
                cur_node->right = new_node;
                new_node->parent = cur_node;
                cur_node = NULL;                /* terminate the while loop */
            } else {
                cur_node = cur_node->right;     /* Go to the right sub-tree */
            }
        }
    }
    /* Mark that a new node was added */
    tree->iSize++;
    /* Fix up the tree properties */
    rbtree_insert_fixup(tree, new_node);  
    return new_node;
}
/* Insert a new object to the tree as the a successor of a given node */
red_black_node_t * insert_successor_at(red_black_tree_t * tree,
                                     red_black_node_t * at_node, void * object)
{
    red_black_node_t * parent;
    red_black_node_t * new_node;
  
    if (!(tree->root)) {
        /* Assign a new root node. Notice that the root is always black */
        new_node = rbnode_construct(object, rbcBlack);
        if (!new_node) return NULL;
        tree->root = new_node;
        tree->iSize = 1;
        return new_node;
    }
    /* Insert the new object as a red leaf, being the successor of node */
    new_node = rbnode_construct(object, rbcRed);
    if (!new_node) return NULL;
    if (!at_node) {
        /* The new node should become the tree minimum: Place is as the left
         * child of the current minimal leaf.
         */
        parent = rbnode_minimum(tree->root);
        parent->left = new_node;
    } else {
        /* Make sure the insertion does not violate the tree order */
        /* In case given node has no right child, place the new node as its 
         * right child. Otherwise, place it at the leftmost position at the
         * sub-tree rooted at its right side.
         */
        if (!at_node->right) {
            parent = at_node;
            parent->right = new_node;
        } else {
            parent = rbnode_minimum(at_node->right);
            parent->left = new_node;
        }
    }
    new_node->parent = parent;
    /* Mark that a new node was added */
    tree->iSize++;
    /* Fix up the tree properties */
    rbtree_insert_fixup(tree, new_node);  
    return new_node;
}
/* Insert a new object to the tree as the a predecessor of a given node */
red_black_node_t * insert_predecessor_at(red_black_tree_t * tree,
                                       red_black_node_t * at_node, void * object)
{
    red_black_node_t * parent;
    red_black_node_t * new_node;
  
    if (!(tree->root)) {
        /* Assign a new root node. Notice that the root is always black */
        new_node = rbnode_construct(object, rbcBlack);
        if (!new_node) return NULL;
        tree->root = new_node;
        tree->iSize = 1;
        return new_node;
    }
    /* Insert the new object as a red leaf, being the predecessor of at_node */
    new_node = rbnode_construct(object, rbcRed);
    if (!new_node) return NULL;
    if (!at_node) {
        /* The new node should become the tree maximum: Place is as the right
         * child of the current maximal leaf.
         */
        parent = rbnode_maximum(tree->root);
        parent->right = new_node;
    } else {
        /* Make sure the insertion does not violate the tree order */
        /* In case given node has no left child, place the new node as its 
         * left child. Otherwise, place it at the rightmost position at the
         * sub-tree rooted at its left side.
         */
        if (!(at_node->left)) {
            parent = at_node;
            parent->left = new_node;
        } else {
            parent = rbnode_maximum (at_node->left);
            parent->right = new_node;
        }
    }
    new_node->parent = parent;
    /* Mark that a new node was added */
    tree->iSize++;
    /* Fix up the tree properties */
    rbtree_insert_fixup(tree, new_node);  
    return new_node;
}
/* Remove an object from the tree */
void rbtree_remove(red_black_tree_t * tree, void * object)
{
    red_black_node_t * node = rbtree_find(tree, object);    /* find the node */
    rbtree_remove_at(tree, node);                         /* remove the node */
}
/* Remove the object pointed by the given node. */
void rbtree_remove_at(red_black_tree_t * tree, red_black_node_t * node)
{
    red_black_node_t * child = NULL;
    /* In case of deleting the single object stored in the tree, free the root,
     * thus emptying the tree.
     */
    if (tree->iSize == 1) {
        rbnode_destruct(tree->root);
        tree->root = NULL;
        tree->iSize = 0;
        return;
    }
    /* Remove the given node from the tree */
    if (node->left && node->right) {
        /* If the node we want to remove has two children, find its successor,
         * which is the leftmost child in its right sub-tree and has at most
         * one child (it may have a right child).
         */
        red_black_node_t * succ_node = rbnode_minimum(node->right);
        /* Now physically swap node and its successor. Notice this may temporarily
         * violate the tree properties, but we are going to remove node anyway.
         * This way we have moved node to a position were it is more convinient
         * to delete it.
         */
        int immediate_succ = (node->right == succ_node);
        red_black_node_t * succ_parent = succ_node->parent;
        red_black_node_t * succ_left = succ_node->left;
        red_black_node_t * succ_right = succ_node->right;
        red_black_color_enum succ_color = succ_node->color;
        succ_node->parent = node->parent;
        succ_node->left = node->left;
        succ_node->right = immediate_succ ? node : node->right;
        succ_node->color = node->color;
        node->parent = immediate_succ ? succ_node : succ_parent;
        node->left = succ_left;
        node->right = succ_right;
        node->color = succ_color;
        if (!immediate_succ) { 
            if (succ_node == node->parent->left)
                node->parent->left = node;
            else
                node->parent->right = node;
        }
        if (node->left)
            node->left->parent = node;
        if (node->right)
            node->right->parent = node;
        if (succ_node->parent) {
            if (node == succ_node->parent->left)
           succ_node->parent->left = succ_node;
            else
           succ_node->parent->right = succ_node;
        } else {
            tree->root = succ_node;
        }
        if (succ_node->left)
            succ_node->left->parent = succ_node;
        if (succ_node->right)
            succ_node->right->parent = succ_node;
    }
    /* At this stage, the node we are going to remove has at most one child */
    child = (node->left) ? node->left : node->right;
    /* Splice out the node to be removed, by linking its parent straight to the 
     * removed node's single child.
     */
    if (child)
        child->parent = node->parent;
    
    if (!(node->parent)) {
        /* If we are deleting the root, make the child the new tree node */
        tree->root = child;
    } else {
        /* Link the removed node parent to its child */
        if (node == node->parent->left) {
            node->parent->left = child;
        } else {
            node->parent->right = child;
        }
    }
    /* Fix-up the red-black properties that may have been damaged: If we have
     * just removed a black node, the black-depth property is no longer valid.
     */
    if (node->color == rbcBlack && child)
        rbtree_remove_fixup(tree, child);
    /* Delete the un-necessary node (we nullify both its children because the 
     * node's destructor is recursive).
     */
    node->left = NULL;
    node->right = NULL;
    free(node);
    /* Descrease the number of objects in the tree */
    tree->iSize--;
}
/* Get the tree minimum */
red_black_node_t * rbtree_minimum(red_black_tree_t * tree)
{
    if (!(tree->root))
        return NULL;
    /* Return the leftmost leaf in the tree */
    return rbnode_minimum(tree->root);
}
/* Get the tree maximum */
red_black_node_t * rbtree_maximum(red_black_tree_t * tree)
{
    if (!(tree->root))
        return NULL;
    /* Return the rightmost leaf in the tree */
    return rbnode_maximum(tree->root);
}
/* Return a pointer to the node containing the given object */
red_black_node_t * rbtree_find(red_black_tree_t * tree, void * object)
{
    red_black_node_t * cur_node = tree->root;
    int comp_result;
    while (cur_node) {
        /* In case of equality, we can return the current node. */
        if ((comp_result = (*(tree->comp))(object, cur_node->object)) == 0)
            return cur_node;
        /* Go down to the left or right child. */
        cur_node = (comp_result > 0) ? cur_node->left : cur_node->right;
    }
    /* If we reached here, the object is not found in the tree */
    return NULL;
}
/* Left-rotate the sub-tree spanned by the given node:
 *
 *          |          RoateRight(y)            |
 *          y         -------------->           x
 *        /   \                               /   \       .
 *       x     T3       RoatateLeft(x)       T1    y      .
 *     /   \          <--------------            /   \    .
 *    T1    T2                                  T2    T3
 */
void rbtree_rotate_left(red_black_tree_t * tree, red_black_node_t * x_node)
{
    /* Get the right child of the node */
    red_black_node_t * y_node = x_node->right;
    /* Change its left subtree (T2) to x's right subtree */
    x_node->right = y_node->left;
    /* Link T2 to its new parent x */
    if (y_node->left != NULL)
        y_node->left->parent = x_node;
    /* Assign x's parent to be y's parent */
    y_node->parent = x_node->parent;
    if (!(x_node->parent)) {
        /* Make y the new tree root */
        tree->root = y_node;
    } else  {
        /* Assign a pointer to y from x's parent */
        if (x_node == x_node->parent->left) {
            x_node->parent->left = y_node;
        }  else {
            x_node->parent->right = y_node;
        }
    }
    /* Assign x to be y's left child */
    y_node->left = x_node;
    x_node->parent = y_node;
}
/* Right-rotate the sub-tree spanned by the given node */
void rbtree_rotate_right(red_black_tree_t * tree, red_black_node_t * y_node)
{
    /* Get the left child of the node */
    red_black_node_t * x_node = y_node->left;
    /* Change its right subtree (T2) to y's left subtree */
    y_node->left = x_node->right;
    /* Link T2 to its new parent y */
    if (x_node->right != NULL)
    x_node->right->parent = y_node;
    /* Assign y's parent to be x's parent */
    x_node->parent = y_node->parent;
    if (!(y_node->parent)) {
        /* Make x the new tree root */
        tree->root = x_node;
    } else  {
        /* Assign a pointer to x from y's parent */
        if (y_node == y_node->parent->left) {
            y_node->parent->left = x_node;
        } else {
            y_node->parent->right = x_node;
        }
    }
    /* Assign y to be x's right child */
    x_node->right = y_node;
    y_node->parent = x_node;
}
/* Fix-up the tree so it maintains the red-black properties after insertion */
void rbtree_insert_fixup(red_black_tree_t * tree, red_black_node_t * node)
{
    /* Fix the red-black propreties: we may have inserted a red leaf as the 
     * child of a red parent - so we have to fix the coloring of the parent 
     * recursively.
     */
    red_black_node_t * curr_node = node;
    red_black_node_t * grandparent;
    red_black_node_t *uncle;
    assert(node && node->color == rbcRed);
  
    while (curr_node != tree->root && curr_node->parent->color == rbcRed) {
        /* Get a pointer to the current node's grandparent (notice the root is 
         * always black, so the red parent must have a parent).
         */
        grandparent = curr_node->parent->parent;
        
        if (curr_node->parent == grandparent->left) {
            /* If the red parent is a left child, the uncle is the right child of 
             * the grandparent.
             */
            uncle = grandparent->right;
            if (uncle && uncle->color == rbcRed) {
                /* If both parent and uncle are red, color them black and color the 
                 * grandparent red.
                 * In case of a NULL uncle, we treat it as a black node.
                 */
                curr_node->parent->color = rbcBlack;
                uncle->color = rbcBlack;
                grandparent->color = rbcRed;
                /* Move to the grandparent */
                curr_node = grandparent;
            } else {
                /* Make sure the current node is a right child. If not, left-rotate 
                 * the parent's sub-tree so the parent becomes the right child of the 
                 * current node (see _rotate_left).
                 */
                if (curr_node == curr_node->parent->right) {
                    curr_node = curr_node->parent;
                    rbtree_rotate_left(tree, curr_node);
                }
                /* Color the parent black and the grandparent red */
                curr_node->parent->color = rbcBlack;
                grandparent->color = rbcRed;
                /* Right-rotate the grandparent's sub-tree */
                rbtree_rotate_right(tree, grandparent);
            }
        } else {
            /* If the red parent is a right child, the uncle is the left child of 
             * the grandparent.
             */
            uncle = grandparent->left;
            if (uncle && uncle->color == rbcRed) {
                /* If both parent and uncle are red, color them black and color the 
                 * grandparent red.
                 * In case of a NULL uncle, we treat it as a black node.
                 */
                curr_node->parent->color = rbcBlack;
                uncle->color = rbcBlack;
                grandparent->color = rbcRed;
                /* Move to the grandparent */
                curr_node = grandparent;
            } else {
                /* Make sure the current node is a left child. If not, right-rotate 
                 * the parent's sub-tree so the parent becomes the left child of the 
                 * current node.
                 */
                if (curr_node == curr_node->parent->left) {
                    curr_node = curr_node->parent;
                    rbtree_rotate_right(tree, curr_node);
                }
                /* Color the parent black and the grandparent red */
                curr_node->parent->color = rbcBlack;
                grandparent->color = rbcRed;
                /* Left-rotate the grandparent's sub-tree */
                rbtree_rotate_left(tree, grandparent);
            }
        }
    }
    /* Make sure that the root is black */
    tree->root->color = rbcBlack;
}
void rbtree_remove_fixup(red_black_tree_t * tree, red_black_node_t * node)
{
    red_black_node_t * curr_node = node;
    red_black_node_t * sibling;
    while (curr_node != tree->root && curr_node->color == rbcBlack) {
        /* Get a pointer to the current node's sibling (notice that the node's 
         * parent must exist, since the node is not the root).
         */
        if (curr_node == curr_node->parent->left) {
            /* If the current node is a left child, its sibling is the right 
             * child of the parent.
             */
            sibling = curr_node->parent->right;
      
            /* Check the sibling's color. Notice that NULL nodes are treated
             * as if they are colored black.
             */
            if (sibling && sibling->color == rbcRed) {
                /* In case the sibling is red, color it black and rotate.
                 * Then color the parent red (and the grandparent is now black).
                 */
                sibling->color = rbcBlack;
                curr_node->parent->color = rbcRed;
                rbtree_rotate_left(tree, curr_node->parent);
                sibling = curr_node->parent->right;
            }
      
            if (sibling && 
                (!(sibling->left) || sibling->left->color == rbcBlack) && 
                (!(sibling->right) || sibling->right->color == rbcBlack))
            {
                /* If the sibling has two black children, color it red */
                sibling->color = rbcRed;
                if (curr_node->parent->color == rbcRed) {
                    /* If the parent is red, we can safely color it black and terminate
                     * the fix-up process.
                     */
                    curr_node->parent->color = rbcBlack;
                    curr_node = tree->root;      /* In order to stop the while loop */
                } else {
                    /* The black depth of the entire sub-tree rooted at the parent is 
                     * now too small - fix it up recursively.
                     */
                    curr_node = curr_node->parent;
                }
            } else {
                if (!sibling) {
                    /* Take special care of the case of a NULL sibling */
                    if (curr_node->parent->color == rbcRed) {
                        curr_node->parent->color = rbcBlack;
                        curr_node = tree->root;    /* In order to stop the while loop */
                    } else {
                        curr_node = curr_node->parent;
                    }
                } else {
                    /* In this case, at least one of the sibling's children is red. 
                     * It is therfore obvious that the sibling itself is black.
                     */
                    if (sibling->right && sibling->right->color == rbcRed) {
                        /* If the right child of the sibling is red, color it black and
                         * rotate around the current parent.
                         */
                        sibling->right->color = rbcBlack;
                        rbtree_rotate_left(tree, curr_node->parent);
                    } else {
                        /* If the left child of the sibling is red, rotate around the 
                         * sibling, then rotate around the new sibling of our current
                         * node.
                         */
                        rbtree_rotate_right(tree, sibling);
                        sibling = curr_node->parent->right;
                        rbtree_rotate_left(tree, sibling);
                    }
                    /* It is now safe to color the parent black and to terminate the 
                     * fix-up process.
                     */
                    if (curr_node->parent->parent)
                        curr_node->parent->parent->color = curr_node->parent->color;
                    curr_node->parent->color = rbcBlack;
                    curr_node = tree->root;      /* In order to stop the while loop */
                }
            }
        } else {
            /* If the current node is a right child, its sibling is the left 
             * child of the parent.
             */
            sibling = curr_node->parent->left;
            /* Check the sibling's color. Notice that NULL nodes are treated
             * as if they are colored black.
             */
            if (sibling && sibling->color == rbcRed) {
                /* In case the sibling is red, color it black and rotate.
                 * Then color the parent red (and the grandparent is now black).
                 */
                sibling->color = rbcBlack;
                curr_node->parent->color = rbcRed;
                rbtree_rotate_right(tree, curr_node->parent);
                sibling = curr_node->parent->left;
            }
            if (sibling &&
                (!(sibling->left) || sibling->left->color == rbcBlack) && 
                (!(sibling->right) || sibling->right->color == rbcBlack))
            {
                /* If the sibling has two black children, color it red */
                sibling->color = rbcRed;
                if (curr_node->parent->color == rbcRed) {
                    /* If the parent is red, we can safely color it black and terminate
                     * the fix-up process.
                     */
                    curr_node->parent->color = rbcBlack;
                    curr_node = tree->root;      /* In order to stop the while loop */
                } else {
                    /* The black depth of the entire sub-tree rooted at the parent is 
                     * now too small - fix it up recursively.
                     */
                    curr_node = curr_node->parent;
                }
            } else {
                if (!sibling) {
                    /* Take special care of the case of a NULL sibling */
                    if (curr_node->parent->color == rbcRed) {
                        curr_node->parent->color = rbcBlack;
                        curr_node = tree->root;    /* In order to stop the while loop */
                    } else {
                        curr_node = curr_node->parent;
                    }
                } else {
                    /* In this case, at least one of the sibling's children is red. 
                     * It is therfore obvious that the sibling itself is black.
                     */
                    if (sibling->left && sibling->left->color == rbcRed) {
                        /* If the left child of the sibling is red, color it black and
                         * rotate around the current parent
                         */
                        sibling->left->color = rbcBlack;
                        rbtree_rotate_right(tree, curr_node->parent);
                    } else {
                        /* If the right child of the sibling is red, rotate around the 
                         * sibling, then rotate around the new sibling of our current 
                         * node
                         */
                        rbtree_rotate_left(tree, sibling);
                        sibling = curr_node->parent->left;
                        rbtree_rotate_right(tree, sibling);
                    }
                    /* It is now safe to color the parent black and to terminate the 
                     * fix-up process.
                     */
                    if (curr_node->parent->parent)
                        curr_node->parent->parent->color = curr_node->parent->color;
                    curr_node->parent->color = rbcBlack;
                    curr_node = tree->root;       /* In order to stop the while loop */
                }
            }
        }
    }
    /* The root can always be colored black */
    curr_node->color = rbcBlack;
}
/* Traverse a red-black tree */
void rbtree_traverse(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param)
{
    rbnode_traverse(tree->root, op, param);
}
/* Right-first traverse a red-black tree */
void rbtree_traverse_right(red_black_tree_t * tree, pfcbRBTreeOperFunc * op, void *param)
{
    rbnode_traverse_right(tree->root, op, param);



view plaincopy to clipboardprint?
//   
// rbtree_test.c   
// by cheungmine   
//   
#include <stdio.h>   
#include <stdlib.h>   
#include <assert.h>   
// RBTREE_SUPPORTS_MULTI_OBJECTS 在下面的文件中被定义,如果不想支持多图,注释掉它   
#include "red_black_tree.h"   
  
/*!  
 */  
int cmp_int(int a, int b)   
{   
  return (a > b) ? -1 : ((a == b) ? 0 : 1);   
}   
/*!  
 */  
void my_print(int value)   
{   
  printf("%d ", value);   
}   
#if !defined(RBTREE_SUPPORTS_MULTI_OBJECTS)   
void test_rbtree_insert_repeat()   
{   
    int i, n;   
       
    red_black_tree_t  tree;   
    red_black_node_t *node, *node2;   
    n = 20;   
    rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int);   
    for (i=0; i<n; i++){   
      rbtree_insert(&tree, (void*) i);   
    }   
    node = rbtree_find(&tree, (void*) 5);   
    assert(node);   
    node2 = rbtree_insert(&tree, (void*) 5);   
    assert(node2);   
    assert(node!=node2);   
    node = rbtree_find(&tree, (void*) 10);   
    assert(node);   
    node2 = rbtree_insert(&tree, (void*) 10);   
    assert(node2);   
    assert(node!=node2);   
    printf("n = %d, d = %d\n", n, rbtree_depth(&tree));   
    rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print);   
    printf("\n");   
    rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print);   
    printf("\n");   
    rbtree_clean(&tree);   
}   
#endif   
void test_rbtree_insert_unique()   
{   
    int i, n;   
       
    red_black_tree_t  tree;   
    red_black_node_t *node, *node2;   
    n = 20;   
    rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int);   
    for (i=0; i<n; i++){   
      rbtree_insert_unique(&tree, (void*) i);   
    }   
    node = rbtree_find(&tree, (void*) 5);   
    assert(node);   
    node2 = rbtree_insert_unique(&tree, (void*) 5);   
    assert(node2);   
    assert(node==node2);   
    node = rbtree_find(&tree, (void*) 10);   
    assert(node);   
    node2 = rbtree_insert_unique(&tree, (void*) 10);   
    assert(node2);   
    assert(node==node2);   
    printf("n = %d, d = %d\n", n, rbtree_depth(&tree));   
    rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print, 0);   
    printf("\n");   
    rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print, 0);   
    printf("\n");   
    rbtree_clean(&tree);   
}   
#ifdef RBTREE_SUPPORTS_MULTI_OBJECTS   
typedef struct _MYOBJECT   
{   
    struct _MYOBJECT *__next_object;   
    int  data;   
}MYOBJECT;   
int cmp_int_multimap(MYOBJECT *a, MYOBJECT *b)   
{   
  return (a->data > b->data) ? -1 : ((a->data == b->data) ? 0 : 1);   
}   
/*!  
 */  
void my_print_multimap(MYOBJECT *obj)   
{   
    while (obj) {   
        printf("%d ", obj->data);   
        obj = obj->__next_object;   
    }   
}   
void test_rbtree_insert_multimap()   
{   
    int i, n;   
    MYOBJECT *obj;   
    MYOBJECT **objects;   
    red_black_tree_t  tree;   
    red_black_node_t *node;   
    n = 20;   
    rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int_multimap);   
    objects = (MYOBJECT**) calloc(n, sizeof(MYOBJECT*));   
    for (i=0; i<n; i++){   
        obj = (MYOBJECT*) malloc(sizeof(MYOBJECT));   
        objects[i] = obj;   
        obj->__next_object = 0;  // MUST be NULL   
        obj->data = i;   
           
        rbtree_insert(&tree, (void*) obj);   
    }   
    rbtree_insert(&tree, (void*) objects[5]);   
    obj = (MYOBJECT*) malloc(sizeof(MYOBJECT));   
    obj->__next_object = 0;  // MUST be NULL   
    obj->data = 5;   
    rbtree_insert(&tree, (void*) obj);   
               
    printf("n = %d, d = %d\n", n, rbtree_depth(&tree));   
    printf("(");   
    node = rbtree_find(&tree, (void*) objects[5]);   
    if (node){   
        MYOBJECT *obj = node->object;   
        while (obj) {   
            printf("%d ", obj->data);   
            obj = obj->__next_object;   
        }   
    }   
    printf(")\n");   
    rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print_multimap, 0);   
    printf("\n");   
    rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print_multimap, 0);   
    printf("\n");   
    rbtree_clean(&tree);   
    for (i=0; i<n; i++){   
        free(objects[i]);   
    }   
    free(objects);   
    free(obj);   
}   
#endif // RBTREE_SUPPORTS_MULTI_OBJECTS   
int main(int argc, char * argv[])   
{   
#if !defined(RBTREE_SUPPORTS_MULTI_OBJECTS)   
    test_rbtree_insert_repeat();   
#endif   
    test_rbtree_insert_unique();   
    test_rbtree_insert_multimap();   
    return 0;   
}  
//
// rbtree_test.c
// by cheungmine
//
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// RBTREE_SUPPORTS_MULTI_OBJECTS 在下面的文件中被定义,如果不想支持多图,注释掉它
#include "red_black_tree.h"


/*!
 */
int cmp_int(int a, int b)
{
  return (a > b) ? -1 : ((a == b) ? 0 : 1);
}
/*!
 */
void my_print(int value)
{
  printf("%d ", value);
}
#if !defined(RBTREE_SUPPORTS_MULTI_OBJECTS)
void test_rbtree_insert_repeat()
{
    int i, n;
    
    red_black_tree_t  tree;
    red_black_node_t *node, *node2;
    n = 20;
    rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int);
    for (i=0; i<n; i++){
      rbtree_insert(&tree, (void*) i);
    }
    node = rbtree_find(&tree, (void*) 5);
    assert(node);
    node2 = rbtree_insert(&tree, (void*) 5);
    assert(node2);
    assert(node!=node2);
    node = rbtree_find(&tree, (void*) 10);
    assert(node);
    node2 = rbtree_insert(&tree, (void*) 10);
    assert(node2);
    assert(node!=node2);
    printf("n = %d, d = %d\n", n, rbtree_depth(&tree));
    rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print);
    printf("\n");
    rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print);
    printf("\n");
    rbtree_clean(&tree);
}
#endif
void test_rbtree_insert_unique()
{
    int i, n;
    
    red_black_tree_t  tree;
    red_black_node_t *node, *node2;
    n = 20;
    rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int);
    for (i=0; i<n; i++){
      rbtree_insert_unique(&tree, (void*) i);
    }
    node = rbtree_find(&tree, (void*) 5);
    assert(node);
    node2 = rbtree_insert_unique(&tree, (void*) 5);
    assert(node2);
    assert(node==node2);
    node = rbtree_find(&tree, (void*) 10);
    assert(node);
    node2 = rbtree_insert_unique(&tree, (void*) 10);
    assert(node2);
    assert(node==node2);
    printf("n = %d, d = %d\n", n, rbtree_depth(&tree));
    rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print, 0);
    printf("\n");
    rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print, 0);
    printf("\n");
    rbtree_clean(&tree);
}
#ifdef RBTREE_SUPPORTS_MULTI_OBJECTS
typedef struct _MYOBJECT
{
    struct _MYOBJECT *__next_object;
    int  data;
}MYOBJECT;
int cmp_int_multimap(MYOBJECT *a, MYOBJECT *b)
{
  return (a->data > b->data) ? -1 : ((a->data == b->data) ? 0 : 1);
}
/*!
 */
void my_print_multimap(MYOBJECT *obj)
{
    while (obj) {
        printf("%d ", obj->data);
        obj = obj->__next_object;
    }
}
void test_rbtree_insert_multimap()
{
    int i, n;
    MYOBJECT *obj;
    MYOBJECT **objects;
    red_black_tree_t  tree;
    red_black_node_t *node;
    n = 20;
    rbtree_init(&tree, (pfcbRBTreeCompFunc*) cmp_int_multimap);
    objects = (MYOBJECT**) calloc(n, sizeof(MYOBJECT*));
    for (i=0; i<n; i++){
        obj = (MYOBJECT*) malloc(sizeof(MYOBJECT));
        objects[i] = obj;
        obj->__next_object = 0;  // MUST be NULL
        obj->data = i;
        
        rbtree_insert(&tree, (void*) obj);
    }
    rbtree_insert(&tree, (void*) objects[5]);
    obj = (MYOBJECT*) malloc(sizeof(MYOBJECT));
    obj->__next_object = 0;  // MUST be NULL
    obj->data = 5;
    rbtree_insert(&tree, (void*) obj);
            
    printf("n = %d, d = %d\n", n, rbtree_depth(&tree));
    printf("(");
    node = rbtree_find(&tree, (void*) objects[5]);
    if (node){
        MYOBJECT *obj = node->object;
        while (obj) {
            printf("%d ", obj->data);
            obj = obj->__next_object;
        }
    }
    printf(")\n");
    rbtree_traverse(&tree, (pfcbRBTreeOperFunc*) my_print_multimap, 0);
    printf("\n");
    rbtree_traverse_right(&tree, (pfcbRBTreeOperFunc*) my_print_multimap, 0);
    printf("\n");
    rbtree_clean(&tree);
    for (i=0; i<n; i++){
        free(objects[i]);
    }
    free(objects);
    free(obj);
}
#endif // RBTREE_SUPPORTS_MULTI_OBJECTS
int main(int argc, char * argv[])
{
#if !defined(RBTREE_SUPPORTS_MULTI_OBJECTS)
    test_rbtree_insert_repeat();
#endif
    test_rbtree_insert_unique();
    test_rbtree_insert_multimap();
    return 0;
}
 




  
原创粉丝点击