1b10db | 2002-10-08 | Martin Nilsson | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
#ifndef RBTREE_H
#define RBTREE_H
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
881484 | 2001-05-01 | Martin Stjernholm | | #include "array.h"
|
c550c2 | 2001-04-30 | Martin Stjernholm | | |
eed89d | 2001-12-10 | Martin Stjernholm | | * o The root node is always black (by convention).
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
|
eed89d | 2001-12-10 | Martin Stjernholm | | * The longest possible path in a given tree thus has alternating red
* and black nodes, and the shortest possible path in it has only
|
c550c2 | 2001-04-30 | Martin Stjernholm | | * black nodes. Therefore it's guaranteed that the longest path is at
|
eed89d | 2001-12-10 | Martin Stjernholm | | * most twice as long as the shortest one. That ensures O(log n) steps
* to follow the path down to any node in any tree of size n.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | */
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr
{
|
c550c2 | 2001-04-30 | Martin Stjernholm | | struct rb_node_hdr *prev, *next;
|
eed89d | 2001-12-10 | Martin Stjernholm | | unsigned INT16 flags;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | };
#define RB_RED 0x2000
#define RB_THREAD_PREV 0x4000
#define RB_THREAD_NEXT 0x8000
#define RB_FLAG_MASK 0xe000
|
eed89d | 2001-12-10 | Martin Stjernholm | | * otherwise be NULL, and it points to the next smaller/bigger
* element. More specifically, the next thread pointer points to the
* closest parent node whose prev pointer subtree contains it, and
* vice versa for the prev thread pointer:
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* p <. .> p
* / . . \
* / . . \
* a . . a
* / \ . . / \
* \ . . /
* b . . b
* / \ . <- next prev -> . / \
* ... . thread pointer . ...
* \ . . /
* c . . c
* / \.. ../ \
*/
|
eed89d | 2001-12-10 | Martin Stjernholm | | #define keep_flags(node, code) do { \
INT16 kept_flags_ = (node)->flags; \
{code;} \
(node)->flags = \
((node)->flags & ~RB_FLAG_MASK) | (kept_flags_ & RB_FLAG_MASK); \
} while (0)
PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *root);
PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *root);
PMOD_EXPORT struct rb_node_hdr *rb_link_prev (struct rb_node_hdr *node);
PMOD_EXPORT struct rb_node_hdr *rb_link_next (struct rb_node_hdr *node);
#define rb_prev(node) \
(DO_IF_RB_STATS (rb_num_sidesteps++ COMMA) \
(node)->flags & RB_THREAD_PREV ? \
DO_IF_RB_STATS (rb_num_sidestep_ops++ COMMA) (node)->prev : \
rb_link_prev (node))
#define rb_next(node) \
(DO_IF_RB_STATS (rb_num_sidesteps++ COMMA) \
(node)->flags & RB_THREAD_NEXT ? \
DO_IF_RB_STATS (rb_num_sidestep_ops++ COMMA) (node)->next : \
rb_link_next (node))
|
881484 | 2001-05-01 | Martin Stjernholm | |
#ifdef PIKE_DEBUG
|
eed89d | 2001-12-10 | Martin Stjernholm | | static inline struct rb_node_hdr *rb_node_check (struct rb_node_hdr *node)
{return node;}
|
881484 | 2001-05-01 | Martin Stjernholm | | #else
|
eed89d | 2001-12-10 | Martin Stjernholm | | #define rb_node_check(node) ((struct rb_node_hdr *) (node))
|
881484 | 2001-05-01 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | typedef int rb_find_fn (void *key, struct rb_node_hdr *node);
typedef int rb_cmp_fn (struct rb_node_hdr *a, struct rb_node_hdr *b, void *extra);
typedef int rb_equal_fn (struct rb_node_hdr *a, struct rb_node_hdr *b, void *extra);
typedef struct rb_node_hdr *rb_copy_fn (struct rb_node_hdr *node, void *extra);
typedef void rb_free_fn (struct rb_node_hdr *node, void *extra);
|
881484 | 2001-05-01 | Martin Stjernholm | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | |
eed89d | 2001-12-10 | Martin Stjernholm | | * already, replaces it otherwise. If there are several entries
* with the same index, the last one of them is replaced. Returns
* the added or replaced node.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* add:
* Adds a new entry, even if one with the same index already
|
eed89d | 2001-12-10 | Martin Stjernholm | | * exists. The entry is added after all other entries with the
* same index. Returns the newly created node.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* add_after:
|
eed89d | 2001-12-10 | Martin Stjernholm | | * Adds a new entry after the given one. Give NULL to add at
* front. Returns the newly created node. Note that it's a linear
* search to get the right entry among several with the same
* index.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* delete:
|
eed89d | 2001-12-10 | Martin Stjernholm | | * Deletes an entry with the specified index, if one exists. If
* there are several entries with the specified index, the last
* one is deleted. Returns nonzero if a node was deleted, zero
* otherwise.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* delete_node:
* Deletes the given node from the tree. Useful to get the right
* entry when several have the same index. The node is assumed to
* exist in the tree. Note that it's a linear search to get the
|
eed89d | 2001-12-10 | Martin Stjernholm | | * right entry among several with the same index.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* find_eq:
|
eed89d | 2001-12-10 | Martin Stjernholm | | * Returns the last entry which has the given index, or zero if
* none exists.
|
c550c2 | 2001-04-30 | Martin Stjernholm | | *
* find_lt, find_gt, find_le, find_ge:
* find_lt and find_le returns the biggest entry which satisfy the
* condition, and vice versa for the other two. This means that
* e.g. rb_next when used on the returned node from find_le never
* returns an entry with the same index.
*
|
eed89d | 2001-12-10 | Martin Stjernholm | | * get_nth:
* Returns the nth entry, counting from the beginning. Note that
* this is a linear operation.
*
|
c550c2 | 2001-04-30 | Martin Stjernholm | | * All destructive operations might change the tree root.
*/
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *rb_insert (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *new);
void rb_add (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *new);
void rb_add_after (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *new,
struct rb_node_hdr *existing);
struct rb_node_hdr *rb_remove (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key);
void rb_remove_node (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *node);
struct rb_node_hdr *rb_remove_with_move (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
size_t node_size,
rb_free_fn *cleanup_fn,
void *cleanup_fn_extra);
struct rb_node_hdr *rb_remove_node_with_move (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *node,
size_t node_size);
struct rb_node_hdr *rb_find_eq (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key);
struct rb_node_hdr *rb_find_lt (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key);
struct rb_node_hdr *rb_find_gt (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key);
struct rb_node_hdr *rb_find_le (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key);
struct rb_node_hdr *rb_find_ge (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key);
struct rb_node_hdr *rb_get_nth (struct rb_node_hdr *root, size_t n);
size_t rb_sizeof (struct rb_node_hdr *root);
void rb_free (struct rb_node_hdr *root, rb_free_fn *free_node_fn, void *extra);
int rb_equal (struct rb_node_hdr *a, struct rb_node_hdr *b,
rb_equal_fn *node_equal_fn, void *extra);
struct rb_node_hdr *rb_copy (struct rb_node_hdr *source,
rb_copy_fn *copy_node_fn, void *extra);
struct rb_node_hdr *rb_make_list (struct rb_node_hdr *tree);
struct rb_node_hdr *rb_make_tree (struct rb_node_hdr *list, size_t length);
#define PIKE_MERGE_DESTR_A 0x2000
#define PIKE_MERGE_DESTR_B 0x1000
enum rb_merge_trees {MERGE_TREE_A, MERGE_TREE_B, MERGE_TREE_RES};
typedef struct rb_node_hdr *rb_merge_copy_fn (struct rb_node_hdr *node, void *extra,
enum rb_merge_trees tree);
typedef void rb_merge_free_fn (struct rb_node_hdr *node, void *extra,
enum rb_merge_trees tree);
struct rb_node_hdr *rb_linear_merge (
struct rb_node_hdr *a, struct rb_node_hdr *b, int operation,
rb_cmp_fn *cmp_fn, void *cmp_fn_extra,
rb_merge_copy_fn *copy_node_fn, void *copy_fn_extra,
rb_merge_free_fn *free_node_fn, void *free_fn_extra,
size_t *length);
#ifdef RB_STATS
extern size_t rb_num_sidesteps, rb_num_sidestep_ops;
extern size_t rb_num_finds, rb_find_depth;
extern size_t rb_num_tracks, rb_track_depth;
extern size_t rb_num_sidetracks, rb_num_sidetrack_ops;
extern size_t rb_max_depth;
extern size_t rb_num_traverses, rb_num_traverse_ops;
extern size_t rbstack_slice_allocs;
extern size_t rb_num_adds, rb_add_rebalance_cnt;
extern size_t rb_num_deletes, rb_del_rebalance_cnt;
void reset_rb_stats();
void print_rb_stats (int reset);
#define DO_IF_RB_STATS(X) X
#else
#define DO_IF_RB_STATS(X)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif /* RBTREE_H */
|