Main Page | Class List | Directories | File List | Class Members | File Members

rbtree.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: rbtree.h,v 1.10 2003/04/02 19:22:44 mast Exp $
00006 */
00007 
00008 /* An implementation of a threaded red/black balanced binary tree.
00009  *
00010  * Created 2001-04-27 by Martin Stjernholm
00011  */
00012 
00013 #ifndef RBTREE_H
00014 #define RBTREE_H
00015 
00016 /* #define RB_STATS */
00017 
00018 #include "array.h"
00019 
00020 /* A red/black tree is a binary tree with one extra bit of info in
00021  * each node - the color of it. The following properties holds:
00022  *
00023  * o  Every node is either red or black.
00024  * o  A NULL leaf is considered black.
00025  * o  If a node is red, its children must be black.
00026  * o  Every path from a node down to all its leafs have the same
00027  *    number of black nodes.
00028  * o  The root node is always black (by convention).
00029  *
00030  * The longest possible path in a given tree thus has alternating red
00031  * and black nodes, and the shortest possible path in it has only
00032  * black nodes. Therefore it's guaranteed that the longest path is at
00033  * most twice as long as the shortest one. That ensures O(log n) steps
00034  * to follow the path down to any node in any tree of size n.
00035  */
00036 
00037 struct rb_node_hdr
00038 {
00039   struct rb_node_hdr *prev, *next;
00040   unsigned INT16 flags;         /* Only the top three bits are used;
00041                                  * may be overlaid. */
00042 };
00043 
00044 #define RB_RED          0x2000
00045 #define RB_THREAD_PREV  0x4000
00046 #define RB_THREAD_NEXT  0x8000
00047 #define RB_FLAG_MASK    0xe000
00048 
00049 /* The thread flags indicate whether the prev/next pointers are thread
00050  * pointers. A thread pointer is used whenever the pointer would
00051  * otherwise be NULL, and it points to the next smaller/bigger
00052  * element. More specifically, the next thread pointer points to the
00053  * closest parent node whose prev pointer subtree contains it, and
00054  * vice versa for the prev thread pointer:
00055  *
00056  *               p <.                                  .> p
00057  *              /    .                                .    \
00058  *             /      .                              .      \
00059  *            a        .                            .        a
00060  *           / \        .                          .        / \
00061  *              \        .                        .        /
00062  *               b        .                      .        b
00063  *              / \       . <- next      prev -> .       / \
00064  *                ...     .    thread pointer    .     ...
00065  *                  \     .                      .     /
00066  *                   c   .                        .   c
00067  *                  / \..                          ../ \
00068  */
00069 
00070 #define keep_flags(node, code) do {                                     \
00071     int kept_flags_ = (node)->flags;                                    \
00072     {code;}                                                             \
00073     (node)->flags =                                                     \
00074       ((node)->flags & ~RB_FLAG_MASK) | (kept_flags_ & RB_FLAG_MASK);   \
00075   } while (0)
00076 
00077 PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *root);
00078 PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *root);
00079 PMOD_EXPORT struct rb_node_hdr *rb_link_prev (struct rb_node_hdr *node);
00080 PMOD_EXPORT struct rb_node_hdr *rb_link_next (struct rb_node_hdr *node);
00081 
00082 #define rb_prev(node)                                                   \
00083   (DO_IF_RB_STATS (rb_num_sidesteps++ COMMA)                            \
00084    (node)->flags & RB_THREAD_PREV ?                                     \
00085    DO_IF_RB_STATS (rb_num_sidestep_ops++ COMMA) (node)->prev :          \
00086    rb_link_prev (node))
00087 #define rb_next(node)                                                   \
00088   (DO_IF_RB_STATS (rb_num_sidesteps++ COMMA)                            \
00089    (node)->flags & RB_THREAD_NEXT ?                                     \
00090    DO_IF_RB_STATS (rb_num_sidestep_ops++ COMMA) (node)->next :          \
00091    rb_link_next (node))
00092 
00093 #ifdef PIKE_DEBUG
00094 /* To get good type checking. */
00095 static INLINE struct rb_node_hdr *rb_node_check (struct rb_node_hdr *node)
00096   {return node;}
00097 #else
00098 #define rb_node_check(node) ((struct rb_node_hdr *) (node))
00099 #endif
00100 
00101 typedef int rb_find_fn (void *key, struct rb_node_hdr *node);
00102 typedef int rb_cmp_fn (struct rb_node_hdr *a, struct rb_node_hdr *b, void *extra);
00103 typedef int rb_equal_fn (struct rb_node_hdr *a, struct rb_node_hdr *b, void *extra);
00104 typedef struct rb_node_hdr *rb_copy_fn (struct rb_node_hdr *node, void *extra);
00105 typedef void rb_free_fn (struct rb_node_hdr *node, void *extra);
00106 
00107 /* Operations:
00108  *
00109  * insert:
00110  *     Adds a new entry only if one with the same index doesn't exist
00111  *     already, replaces it otherwise. If there are several entries
00112  *     with the same index, the last one of them is replaced. Returns
00113  *     the added or replaced node.
00114  *
00115  * add:
00116  *     Adds a new entry, even if one with the same index already
00117  *     exists. The entry is added after all other entries with the
00118  *     same index. Returns the newly created node.
00119  *
00120  * add_after:
00121  *     Adds a new entry after the given one. Give NULL to add at
00122  *     front. Returns the newly created node. Note that it's a linear
00123  *     search to get the right entry among several with the same
00124  *     index.
00125  *
00126  * delete:
00127  *     Deletes an entry with the specified index, if one exists. If
00128  *     there are several entries with the specified index, the last
00129  *     one is deleted. Returns nonzero if a node was deleted, zero
00130  *     otherwise.
00131  *
00132  * delete_node:
00133  *     Deletes the given node from the tree. Useful to get the right
00134  *     entry when several have the same index. The node is assumed to
00135  *     exist in the tree. Note that it's a linear search to get the
00136  *     right entry among several with the same index.
00137  *
00138  * find_eq:
00139  *     Returns the last entry which has the given index, or zero if
00140  *     none exists.
00141  *
00142  * find_lt, find_gt, find_le, find_ge:
00143  *     find_lt and find_le returns the biggest entry which satisfy the
00144  *     condition, and vice versa for the other two. This means that
00145  *     e.g. rb_next when used on the returned node from find_le never
00146  *     returns an entry with the same index.
00147  *
00148  * get_nth:
00149  *     Returns the nth entry, counting from the beginning. Note that
00150  *     this is a linear operation.
00151  *
00152  * All destructive operations might change the tree root.
00153  */
00154 
00155 struct rb_node_hdr *rb_insert (struct rb_node_hdr **root,
00156                                rb_find_fn *find_fn, void *key,
00157                                struct rb_node_hdr *new);
00158 void rb_add (struct rb_node_hdr **root,
00159              rb_find_fn *find_fn, void *key,
00160              struct rb_node_hdr *new);
00161 void rb_add_after (struct rb_node_hdr **root,
00162                    rb_find_fn *find_fn, void *key,
00163                    struct rb_node_hdr *new,
00164                    struct rb_node_hdr *existing);
00165 struct rb_node_hdr *rb_remove (struct rb_node_hdr **root,
00166                                rb_find_fn *find_fn, void *key);
00167 void rb_remove_node (struct rb_node_hdr **root,
00168                      rb_find_fn *find_fn, void *key,
00169                      struct rb_node_hdr *node);
00170 struct rb_node_hdr *rb_remove_with_move (struct rb_node_hdr **root,
00171                                          rb_find_fn *find_fn, void *key,
00172                                          size_t node_size,
00173                                          rb_free_fn *cleanup_fn,
00174                                          void *cleanup_fn_extra);
00175 struct rb_node_hdr *rb_remove_node_with_move (struct rb_node_hdr **root,
00176                                               rb_find_fn *find_fn, void *key,
00177                                               struct rb_node_hdr *node,
00178                                               size_t node_size);
00179 
00180 struct rb_node_hdr *rb_find_eq (struct rb_node_hdr *root,
00181                                 rb_find_fn *find_fn, void *key);
00182 struct rb_node_hdr *rb_find_lt (struct rb_node_hdr *root,
00183                                 rb_find_fn *find_fn, void *key);
00184 struct rb_node_hdr *rb_find_gt (struct rb_node_hdr *root,
00185                                 rb_find_fn *find_fn, void *key);
00186 struct rb_node_hdr *rb_find_le (struct rb_node_hdr *root,
00187                                 rb_find_fn *find_fn, void *key);
00188 struct rb_node_hdr *rb_find_ge (struct rb_node_hdr *root,
00189                                 rb_find_fn *find_fn, void *key);
00190 struct rb_node_hdr *rb_get_nth (struct rb_node_hdr *root, size_t n);
00191 size_t rb_sizeof (struct rb_node_hdr *root);
00192 
00193 void rb_free (struct rb_node_hdr *root, rb_free_fn *free_node_fn, void *extra);
00194 int rb_equal (struct rb_node_hdr *a, struct rb_node_hdr *b,
00195               rb_equal_fn *node_equal_fn, void *extra);
00196 struct rb_node_hdr *rb_copy (struct rb_node_hdr *source,
00197                              rb_copy_fn *copy_node_fn, void *extra);
00198 
00199 struct rb_node_hdr *rb_make_list (struct rb_node_hdr *tree);
00200 struct rb_node_hdr *rb_make_tree (struct rb_node_hdr *list, size_t length);
00201 
00202 #define PIKE_MERGE_DESTR_A      0x2000
00203 #define PIKE_MERGE_DESTR_B      0x1000
00204 
00205 enum rb_merge_trees {MERGE_TREE_A, MERGE_TREE_B, MERGE_TREE_RES};
00206 
00207 typedef struct rb_node_hdr *rb_merge_copy_fn (struct rb_node_hdr *node, void *extra,
00208                                               enum rb_merge_trees tree);
00209 typedef void rb_merge_free_fn (struct rb_node_hdr *node, void *extra,
00210                                enum rb_merge_trees tree);
00211 
00212 struct rb_node_hdr *rb_linear_merge (
00213   struct rb_node_hdr *a, struct rb_node_hdr *b, int operation,
00214   rb_cmp_fn *cmp_fn, void *cmp_fn_extra,
00215   rb_merge_copy_fn *copy_node_fn, void *copy_fn_extra,
00216   rb_merge_free_fn *free_node_fn, void *free_fn_extra,
00217   size_t *length);
00218 
00219 #ifdef RB_STATS
00220 extern size_t rb_num_sidesteps, rb_num_sidestep_ops;
00221 extern size_t rb_num_finds, rb_find_depth;
00222 extern size_t rb_num_tracks, rb_track_depth;
00223 extern size_t rb_num_sidetracks, rb_num_sidetrack_ops;
00224 extern size_t rb_max_depth;
00225 extern size_t rb_num_traverses, rb_num_traverse_ops;
00226 extern size_t rbstack_slice_allocs;
00227 extern size_t rb_num_adds, rb_add_rebalance_cnt;
00228 extern size_t rb_num_deletes, rb_del_rebalance_cnt;
00229 void reset_rb_stats();
00230 void print_rb_stats (int reset);
00231 #define DO_IF_RB_STATS(X) X
00232 #else
00233 #define DO_IF_RB_STATS(X)
00234 #endif
00235 
00236 #endif  /* RBTREE_H */

Generated on Fri Jul 22 23:44:27 2005 for Pike by  doxygen 1.3.9.1