Commit 713fd67f authored by David Woodhouse's avatar David Woodhouse

Add three functions for rbtree manipulation -- rb_next(), rb_prev() and rb_replace_node()

    
rb_next() and rb_prev() return the next and previous nodes in the tree, respectively.

rb_replace_node() allows fast replacement of a single node without having to remove the 
victim, rebalance the tree, insert the replacement and then rebalance again to the original
topology.
parent c9581bb6
......@@ -121,6 +121,13 @@ rb_root_t;
extern void rb_insert_color(rb_node_t *, rb_root_t *);
extern void rb_erase(rb_node_t *, rb_root_t *);
/* Find logical next and previous nodes in a tree */
extern rb_node_t *rb_next(rb_node_t *);
extern rb_node_t *rb_prev(rb_node_t *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(rb_node_t *victim, rb_node_t *new, rb_root_t *root);
static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link)
{
node->rb_parent = parent;
......
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -294,3 +295,70 @@ void rb_erase(rb_node_t * node, rb_root_t * root)
__rb_erase_color(child, parent, root);
}
EXPORT_SYMBOL(rb_erase);
rb_node_t *rb_next(rb_node_t *node)
{
/* If we have a right-hand child, go down and then left as far
as we can. */
if (node->rb_right) {
node = node->rb_right;
while (node->rb_left)
node=node->rb_left;
return node;
}
/* No right-hand children. Everything down and left is
smaller than us, so any 'next' node must be in the general
direction of our parent. Go up the tree; any time the
ancestor is a right-hand child of its parent, keep going
up. First time it's a left-hand child of its parent, said
parent is our 'next' node. */
while (node->rb_parent && node == node->rb_parent->rb_right)
node = node->rb_parent;
return node->rb_parent;
}
EXPORT_SYMBOL(rb_next);
rb_node_t *rb_prev(rb_node_t *node)
{
/* If we have a left-hand child, go down and then right as far
as we can. */
if (node->rb_left) {
node = node->rb_left;
while (node->rb_right)
node=node->rb_right;
return node;
}
/* No left-hand children. Go up till we find an ancestor which
is a right-hand child of its parent */
while (node->rb_parent && node == node->rb_parent->rb_left)
node = node->rb_parent;
return node->rb_parent;
}
EXPORT_SYMBOL(rb_prev);
void rb_replace_node(rb_node_t *victim, rb_node_t *new, rb_root_t *root)
{
rb_node_t *parent = victim->rb_parent;
/* Set the surrounding nodes to point to the replacement */
if (parent) {
if (victim == parent->rb_left)
parent->rb_left = new;
else
parent->rb_right = new;
} else {
root->rb_node = new;
}
if (victim->rb_left)
victim->rb_left->rb_parent = new;
if (victim->rb_right)
victim->rb_right->rb_parent = new;
/* Copy the pointers/colour from the victim to the replacement */
*new = *victim;
}
EXPORT_SYMBOL(rb_replace_node);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment