Rewrite of red-black tree code.
This commit is contained in:
parent
f23a530674
commit
3aa5e506b7
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rb.c,v 1.5 2006/09/02 20:46:50 matt Exp $ */
|
||||
/* $NetBSD: rb.c,v 1.6 2006/09/05 04:35:45 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -40,15 +40,21 @@
|
|||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#define KASSERT(s) assert(s)
|
||||
#else
|
||||
#include <lib/libkern/libkern.h>
|
||||
#endif
|
||||
#include "rb.h"
|
||||
|
||||
static void rb_tree_rotate(struct rb_tree *, struct rb_node *, int);
|
||||
static void rb_tree_swap_nodes(struct rb_tree *, struct rb_node *, int);
|
||||
static void rb_tree_insert_rebalance(struct rb_tree *, struct rb_node *);
|
||||
static void rb_tree_removal_rebalance(struct rb_tree *, struct rb_node *);
|
||||
static void rb_tree_removal_rebalance(struct rb_tree *, struct rb_node *,
|
||||
unsigned int);
|
||||
#ifndef NDEBUG
|
||||
static bool rb_tree_check_node(const struct rb_tree *, const struct rb_node *,
|
||||
const struct rb_node *, bool);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Rather than testing for the NULL everywhere, all terminal leaves are
|
||||
|
@ -70,57 +76,78 @@ rb_tree_init(struct rb_tree *rbt, rb_compare_nodes_fn compare_nodes,
|
|||
}
|
||||
|
||||
/*
|
||||
* Rotate the tree between Y and X
|
||||
* X c a Y
|
||||
* a b b c
|
||||
* Swap the location and colors of 'self' and its child @ which. The child
|
||||
* can not be a sentinel node.
|
||||
*/
|
||||
void
|
||||
rb_tree_rotate(struct rb_tree *rbt, struct rb_node *self, int which)
|
||||
rb_tree_swap_nodes(struct rb_tree *rbt, struct rb_node *old_father, int which)
|
||||
{
|
||||
const int other = which ^ RB_OTHER;
|
||||
struct rb_node * const parent = self->rb_parent;
|
||||
struct rb_node * const child = self->rb_nodes[other];
|
||||
const unsigned int other = which ^ RB_OTHER;
|
||||
struct rb_node * const grandpa = old_father->rb_parent;
|
||||
struct rb_node * const old_child = old_father->rb_nodes[which];
|
||||
struct rb_node * const new_father = old_child;
|
||||
struct rb_node * const new_child = old_father;
|
||||
unsigned int properties;
|
||||
|
||||
KASSERT(!child->rb_sentinel);
|
||||
KASSERT(child->rb_parent == self);
|
||||
#if 0
|
||||
(*rbt->rbt_print_node)(child, which ? "before-l " : "before-r ");
|
||||
#endif
|
||||
KASSERT(!RB_SENTINEL_P(old_child));
|
||||
KASSERT(old_child->rb_parent == old_father);
|
||||
|
||||
if ((child->rb_parent = parent) == NULL) {
|
||||
KASSERT(rbt->rbt_root == self);
|
||||
rbt->rbt_root = child;
|
||||
} else {
|
||||
parent->rb_nodes[self->rb_position] = child;
|
||||
KASSERT(rb_tree_check_node(rbt, old_father, NULL, false));
|
||||
KASSERT(rb_tree_check_node(rbt, old_child, NULL, false));
|
||||
KASSERT(RB_ROOT_P(old_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
|
||||
|
||||
/*
|
||||
* Exchange descendant linkages.
|
||||
*/
|
||||
grandpa->rb_nodes[old_father->rb_position] = new_father;
|
||||
new_child->rb_nodes[which] = old_child->rb_nodes[other];
|
||||
new_father->rb_nodes[other] = new_child;
|
||||
|
||||
/*
|
||||
* Update ancestor linkages
|
||||
*/
|
||||
new_father->rb_parent = grandpa;
|
||||
new_child->rb_parent = new_father;
|
||||
|
||||
/*
|
||||
* Exchange properties between new_father and new_child. The only
|
||||
* change is that new_child's position is now on the other side.
|
||||
*/
|
||||
properties = old_child->rb_properties;
|
||||
new_father->rb_properties = old_father->rb_properties;
|
||||
new_child->rb_properties = properties;
|
||||
new_child->rb_position = other;
|
||||
|
||||
/*
|
||||
* Make sure to reparent the new child to ourself.
|
||||
*/
|
||||
if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
|
||||
new_child->rb_nodes[which]->rb_parent = new_child;
|
||||
new_child->rb_nodes[which]->rb_position = which;
|
||||
}
|
||||
|
||||
self->rb_nodes[other] = child->rb_nodes[which];
|
||||
if (!self->rb_nodes[other]->rb_sentinel)
|
||||
self->rb_nodes[other]->rb_parent = self;
|
||||
child->rb_nodes[which] = self;
|
||||
child->rb_position = self->rb_position;
|
||||
self->rb_parent = child;
|
||||
self->rb_position = which;
|
||||
#if 0
|
||||
(*rbt->rbt_print_node)(self, which ? "after-l " : "after-r ");
|
||||
#endif
|
||||
KASSERT(rb_tree_check_node(rbt, new_father, NULL, false));
|
||||
KASSERT(rb_tree_check_node(rbt, new_child, NULL, false));
|
||||
KASSERT(RB_ROOT_P(new_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
|
||||
}
|
||||
|
||||
void
|
||||
rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
{
|
||||
struct rb_node *prev, *next, *tmp, *parent;
|
||||
u_int position = 2;
|
||||
struct rb_node *prev, *next, *parent, *tmp;
|
||||
unsigned int position;
|
||||
|
||||
self->rb_properties = 0;
|
||||
prev = NULL;
|
||||
next = NULL;
|
||||
parent = NULL;
|
||||
tmp = rbt->rbt_root;
|
||||
parent = (struct rb_node *)&rbt->rbt_root;
|
||||
position = RB_LEFT;
|
||||
|
||||
/*
|
||||
* Find out where to place this new leaf.
|
||||
*/
|
||||
while (!tmp->rb_sentinel) {
|
||||
while (!RB_SENTINEL_P(tmp)) {
|
||||
const int diff = (*rbt->rbt_compare_nodes)(tmp, self);
|
||||
parent = tmp;
|
||||
KASSERT(diff != 0);
|
||||
|
@ -139,115 +166,138 @@ rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
|||
/*
|
||||
* Verify our sequential position
|
||||
*/
|
||||
if (prev != NULL && next == NULL)
|
||||
if (prev != NULL && !RB_SENTINEL_P(prev) && next == NULL)
|
||||
next = TAILQ_NEXT(prev, rb_link);
|
||||
if (prev == NULL && next != NULL)
|
||||
if (prev == NULL && (next != NULL && !RB_SENTINEL_P(next)))
|
||||
next = TAILQ_PREV(next, rb_node_qh, rb_link);
|
||||
KASSERT(prev == NULL || (*rbt->rbt_compare_nodes)(prev, self) > 0);
|
||||
KASSERT(next == NULL || (*rbt->rbt_compare_nodes)(self, next) < 0);
|
||||
KASSERT(prev == NULL || RB_SENTINEL_P(prev) || (*rbt->rbt_compare_nodes)(prev, self) > 0);
|
||||
KASSERT(next == NULL || RB_SENTINEL_P(next) || (*rbt->rbt_compare_nodes)(self, next) < 0);
|
||||
|
||||
/*
|
||||
* Initialize the node and insert as a leaf into the tree.
|
||||
*/
|
||||
rbt->rbt_count++;
|
||||
self->rb_parent = parent;
|
||||
if (parent == NULL) {
|
||||
KASSERT(rbt->rbt_root->rb_sentinel);
|
||||
self->rb_position = RB_PARENT;
|
||||
self->rb_left = rbt->rbt_root;
|
||||
self->rb_right = rbt->rbt_root;
|
||||
rbt->rbt_root = self;
|
||||
self->rb_position = position;
|
||||
if (__predict_false(parent == (struct rb_node *) &rbt->rbt_root)) {
|
||||
RB_MARK_ROOT(self);
|
||||
} else {
|
||||
KASSERT(position == RB_LEFT || position == RB_RIGHT);
|
||||
self->rb_position = position;
|
||||
self->rb_left = parent->rb_nodes[position];
|
||||
self->rb_right = parent->rb_nodes[position];
|
||||
parent->rb_nodes[position] = self;
|
||||
KASSERT(!RB_ROOT_P(self)); /* Already done */
|
||||
}
|
||||
KASSERT(RB_SENTINEL_P(parent->rb_nodes[position]));
|
||||
self->rb_left = parent->rb_nodes[position];
|
||||
self->rb_right = parent->rb_nodes[position];
|
||||
parent->rb_nodes[position] = self;
|
||||
KASSERT(self->rb_left == &sentinel_node &&
|
||||
self->rb_right == &sentinel_node);
|
||||
|
||||
/*
|
||||
* Insert the new node into a sorted list for easy sequential access
|
||||
*/
|
||||
if (next != NULL) {
|
||||
rbt->rbt_count++;
|
||||
if (next != NULL && !RB_SENTINEL_P(next)) {
|
||||
TAILQ_INSERT_BEFORE(next, self, rb_link);
|
||||
} else {
|
||||
TAILQ_INSERT_TAIL(&rbt->rbt_nodes, self, rb_link);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Rebalance tree after insertation
|
||||
* Validate the tree before we rebalance
|
||||
*/
|
||||
rb_tree_check(rbt, false);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Rebalance tree after insertion
|
||||
*/
|
||||
rb_tree_insert_rebalance(rbt, self);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Validate the tree after we rebalanced
|
||||
*/
|
||||
rb_tree_check(rbt, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self)
|
||||
{
|
||||
self->rb_red = 1;
|
||||
RB_MARK_RED(self);
|
||||
|
||||
while (self != rbt->rbt_root && self->rb_parent->rb_red) {
|
||||
const int which =
|
||||
while (!RB_ROOT_P(self) && RB_RED_P(self->rb_parent)) {
|
||||
const unsigned int which =
|
||||
(self->rb_parent == self->rb_parent->rb_parent->rb_left
|
||||
? RB_LEFT
|
||||
: RB_RIGHT);
|
||||
const int other = which ^ RB_OTHER;
|
||||
struct rb_node *uncle;
|
||||
const unsigned int other = which ^ RB_OTHER;
|
||||
struct rb_node * father = self->rb_parent;
|
||||
struct rb_node * grandpa = father->rb_parent;
|
||||
struct rb_node * const uncle = grandpa->rb_nodes[other];
|
||||
|
||||
KASSERT(!self->rb_sentinel);
|
||||
KASSERT(!RB_SENTINEL_P(self));
|
||||
/*
|
||||
* We are red, our are parent is red, and our
|
||||
* grandparent is black.
|
||||
* We are red and our parent is red, therefore we must have a
|
||||
* grandfather and he must be black.
|
||||
*/
|
||||
uncle = self->rb_parent->rb_parent->rb_nodes[other];
|
||||
if (uncle->rb_red) {
|
||||
KASSERT(RB_RED_P(self)
|
||||
&& RB_RED_P(father)
|
||||
&& RB_BLACK_P(grandpa));
|
||||
|
||||
if (RB_RED_P(uncle)) {
|
||||
/*
|
||||
* Case 1: our uncle is red
|
||||
* Simply invert the colors of our parent and
|
||||
* uncle and make our grandparent red. And
|
||||
* then solve the problem up at his level.
|
||||
*/
|
||||
uncle->rb_red = 0;
|
||||
self->rb_parent->rb_red = 0;
|
||||
self->rb_parent->rb_parent->rb_red = 1;
|
||||
self = self->rb_parent->rb_parent;
|
||||
} else {
|
||||
/*
|
||||
* Case 2&3: our uncle is black.
|
||||
*/
|
||||
if (self == self->rb_parent->rb_nodes[other]) {
|
||||
/*
|
||||
* Case 2: we are on the same side as our uncle
|
||||
* Rotate parent away from uncle so this
|
||||
* case becomes case 3
|
||||
*/
|
||||
self = self->rb_parent;
|
||||
rb_tree_rotate(rbt, self, which);
|
||||
}
|
||||
/*
|
||||
* Case 3: we are opposite a child of a black uncle.
|
||||
* Change parent to black and grandparent to
|
||||
* red. Rotate grandparent away from ourself.
|
||||
*/
|
||||
self->rb_parent->rb_red = 0;
|
||||
self->rb_parent->rb_parent->rb_red = 1;
|
||||
rb_tree_rotate(rbt, self->rb_parent->rb_parent, other);
|
||||
RB_MARK_BLACK(uncle);
|
||||
RB_MARK_BLACK(father);
|
||||
RB_MARK_RED(grandpa);
|
||||
self = grandpa;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Case 2&3: our uncle is black.
|
||||
*/
|
||||
if (self == father->rb_nodes[other]) {
|
||||
/*
|
||||
* Case 2: we are on the same side as our uncle
|
||||
* Swap ourselves with our parent so this case
|
||||
* becomes case 3. Basically our parent becomes our
|
||||
* child.
|
||||
*/
|
||||
self = father;
|
||||
rb_tree_swap_nodes(rbt, self, other);
|
||||
father = self->rb_parent;
|
||||
grandpa = father->rb_parent;
|
||||
}
|
||||
KASSERT(RB_RED_P(self) && RB_RED_P(father));
|
||||
KASSERT(grandpa->rb_nodes[which] == father);
|
||||
/*
|
||||
* Case 3: we are opposite a child of a black uncle.
|
||||
* Swap our parent and grandparent. Since our grandfather
|
||||
* is black, our father will become black and our new sibling
|
||||
* (former grandparent) will become red.
|
||||
*/
|
||||
rb_tree_swap_nodes(rbt, grandpa, which);
|
||||
KASSERT(RB_RED_P(self) && RB_BLACK_P(father));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Final step: Set the root to black.
|
||||
*/
|
||||
rbt->rbt_root->rb_red = 0;
|
||||
RB_MARK_BLACK(rbt->rbt_root);
|
||||
}
|
||||
|
||||
|
||||
struct rb_node *
|
||||
rb_tree_find(struct rb_tree *rbt, void *key)
|
||||
{
|
||||
struct rb_node *parent = rbt->rbt_root;
|
||||
|
||||
while (!parent->rb_sentinel) {
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const int diff = (*rbt->rbt_compare_key)(parent, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
|
@ -257,116 +307,411 @@ rb_tree_find(struct rb_tree *rbt, void *key)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
rb_tree_remove_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
{
|
||||
struct rb_node *child;
|
||||
/*
|
||||
* Easy case, one or more children is NULL (leaf node or parent of
|
||||
* leaf node).
|
||||
* Easy case, there are no children. This means this node is
|
||||
* at rank [N] (the bottom) of the red-black tree. We can simple just
|
||||
* prune it. This leave the problem of identifying the node removed.
|
||||
* Since the node "left" is a sentinel it doesn't carry any information.
|
||||
* Instead we identify the removed node by parent and position.
|
||||
*/
|
||||
if (self->rb_left->rb_sentinel || self->rb_left->rb_sentinel) {
|
||||
const int which = (!self->rb_left->rb_sentinel ? RB_LEFT : RB_RIGHT);
|
||||
child = self->rb_nodes[which];
|
||||
if (self->rb_parent == NULL) {
|
||||
rbt->rbt_root = child;
|
||||
} else {
|
||||
self->rb_parent->rb_nodes[self->rb_position] = child;
|
||||
}
|
||||
if (child->rb_sentinel)
|
||||
child = self->rb_parent;
|
||||
else
|
||||
child->rb_parent = self->rb_parent;
|
||||
} else {
|
||||
struct rb_node *new_self;
|
||||
child = self->rb_right;
|
||||
while (!child->rb_left->rb_sentinel)
|
||||
child = child->rb_left;
|
||||
new_self = child;
|
||||
KASSERT(new_self == TAILQ_NEXT(self, rb_link));
|
||||
|
||||
/*
|
||||
* Take new_self out of the tree (its only subnode can be on the
|
||||
* right since we know the left subnode is NULL).
|
||||
*/
|
||||
child->rb_parent->rb_left = child->rb_right;
|
||||
if (!child->rb_right->rb_sentinel) {
|
||||
child->rb_right->rb_parent = child->rb_parent;
|
||||
child->rb_right->rb_position = RB_LEFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take self out of the tree and insert new_self into its place.
|
||||
*/
|
||||
new_self->rb_right = self->rb_right;
|
||||
new_self->rb_left = self->rb_left;
|
||||
if (!new_self->rb_right->rb_sentinel)
|
||||
new_self->rb_right->rb_parent = new_self;
|
||||
if (!new_self->rb_left->rb_sentinel)
|
||||
new_self->rb_left->rb_parent = new_self;
|
||||
new_self->rb_red = self->rb_red;
|
||||
new_self->rb_parent = self->rb_parent;
|
||||
/*
|
||||
* Update parent
|
||||
*/
|
||||
if (new_self->rb_parent == NULL) {
|
||||
rbt->rbt_root = new_self;
|
||||
} else {
|
||||
new_self->rb_parent->rb_nodes[self->rb_position] = new_self;
|
||||
}
|
||||
if (RB_CHILDLESS_P(self)) {
|
||||
KASSERT(rb_tree_check_node(rbt, self, NULL, false));
|
||||
self->rb_parent->rb_nodes[self->rb_position] = self->rb_left;
|
||||
if (RB_BLACK_P(self) && !RB_ROOT_P(self))
|
||||
rb_tree_removal_rebalance(rbt,
|
||||
self->rb_parent, self->rb_position);
|
||||
KASSERT(RB_ROOT_P(self) || rb_tree_check_node(rbt, self->rb_parent, NULL, true));
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If this node only has one valid child, that child must be itself
|
||||
* childless. This is because a red-black tree only has leaves at
|
||||
* two ranks, [N-1] and [N]. If this node only has one child at this
|
||||
* rank, this must be rank [N-1] since all nodes at rank [N] are
|
||||
* childless. Thus our child must be at rank [N] and therevore must
|
||||
* be childless.
|
||||
*
|
||||
* Promoting this node's child to rank [N-1] and giving this node's
|
||||
* color allows us to pretend we really removed a node of rank [N].
|
||||
* Now if the child was red, even better since we can just return
|
||||
* knowing that removing a red node from a red-black tree still
|
||||
* leaves a valid red-black tree.
|
||||
*
|
||||
* D \ D \ D
|
||||
* B F > B E > B E
|
||||
* A C E _ / A C _ F / A C _ x
|
||||
*
|
||||
* We are removing F, but F has a child E. So we swap E and F (in
|
||||
* theory but we really replace F by E thereby removing F from the
|
||||
* tree).
|
||||
*/
|
||||
if (!RB_TWOCHILDREN_P(self)) {
|
||||
const unsigned int which = RB_LEFT_SENTINEL_P(self) ? RB_RIGHT : RB_LEFT;
|
||||
const unsigned int other = which ^ RB_OTHER;
|
||||
struct rb_node * const new_self = self->rb_nodes[which];
|
||||
const bool was_black = RB_BLACK_P(new_self);
|
||||
|
||||
KASSERT(RB_CHILDLESS_P(new_self));
|
||||
KASSERT(rb_tree_check_node(rbt, new_self, NULL, false));
|
||||
|
||||
/*
|
||||
* Copy self to new_self.
|
||||
*/
|
||||
self->rb_parent->rb_nodes[self->rb_position] = new_self;
|
||||
new_self->rb_parent = self->rb_parent;
|
||||
new_self->rb_properties = self->rb_properties;
|
||||
new_self->rb_nodes[which] = new_self->rb_nodes[other];
|
||||
KASSERT(rb_tree_check_node(rbt, new_self, NULL, false));
|
||||
if (was_black) {
|
||||
/*
|
||||
* Now rebalance
|
||||
*/
|
||||
rb_tree_removal_rebalance(rbt, new_self, other);
|
||||
} else {
|
||||
/*
|
||||
* If new_self was red, then self must have been black.
|
||||
*/
|
||||
KASSERT(RB_BLACK_P(self));
|
||||
/* RB_MARK_BLACK(new_self); */
|
||||
}
|
||||
KASSERT(rb_tree_check_node(rbt, new_self, NULL, true));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* The node to be removed is in the interior of the red-black tree.
|
||||
* This results in a difficulty in this red-black implementation
|
||||
* since contrary to a traditional implemenation the interior nodes
|
||||
* contain the keys while the leaves have no keys.
|
||||
*
|
||||
* D | C
|
||||
* B F | B F
|
||||
* A C E G | A x E G
|
||||
* 1 2 3 4 5 6 7 | 1 2 3 5 6 7
|
||||
*
|
||||
* We need to remove D. Whom do we swap with, C or E? It doesn't
|
||||
* matter since they are both at rank [N]. We put C as root and
|
||||
* then pretend D was a child B. Even though D's key would never
|
||||
* have been valid at C, since it's now deleted it's key is
|
||||
* irrevalent. We simply claim to have deleted right(B).
|
||||
*
|
||||
* D | E
|
||||
* B F | B F
|
||||
* A E G | A x G
|
||||
* 1 2 4 5 6 7 | 1 2 5 6 7
|
||||
*
|
||||
* We need to remove D. Whom do we swap with? E, of course. E is
|
||||
* the closest node of rank [N]. Always choose the highest rank you
|
||||
* can. We make E root and then pretend D was a child F. Again D's
|
||||
* key is irrevalent. We simply claim to have deleted left(F).
|
||||
*
|
||||
* D | D
|
||||
* B F | B G
|
||||
* A G | A F
|
||||
* 1 2 4 6 7 | 1 2 4 6 7
|
||||
*
|
||||
* We need to remove D. Whom do we swap with? B and F are equally
|
||||
* bad since they both have one child. So we swap one and that
|
||||
* reduces to the previous case.
|
||||
*/
|
||||
if (RB_TWOCHILDREN_P(self)) {
|
||||
struct rb_node * const next = TAILQ_NEXT(self, rb_link);
|
||||
struct rb_node * const prev = TAILQ_PREV(self, rb_node_qh, rb_link);
|
||||
struct rb_node * new_self;
|
||||
struct rb_node * parent;
|
||||
unsigned int which;
|
||||
bool was_black;
|
||||
|
||||
KASSERT(next != NULL && prev != NULL);
|
||||
KASSERT(!RB_TWOCHILDREN_P(next));
|
||||
KASSERT(!RB_TWOCHILDREN_P(prev));
|
||||
|
||||
/*
|
||||
* First, pick the childless victim.
|
||||
* Now we two possible victims
|
||||
* Otherwise, if root, pick from the side with more nodes.
|
||||
* Lastly, pick from the side closest to the root.
|
||||
*/
|
||||
if (RB_CHILDLESS_P(next) && !RB_CHILDLESS_P(prev)) {
|
||||
new_self = next;
|
||||
} else if (RB_CHILDLESS_P(prev) && !RB_CHILDLESS_P(next)) {
|
||||
new_self = prev;
|
||||
} else if (RB_ROOT_P(self)) {
|
||||
new_self = prev;
|
||||
} else {
|
||||
new_self = next;
|
||||
}
|
||||
KASSERT(new_self != rbt->rbt_root);
|
||||
KASSERT(!RB_TWOCHILDREN_P(new_self));
|
||||
|
||||
if (RB_CHILDLESS_P(new_self)) {
|
||||
KASSERT(rb_tree_check_node(rbt, new_self, NULL, false));
|
||||
which = new_self->rb_position;
|
||||
parent = new_self->rb_parent;
|
||||
was_black = RB_BLACK_P(new_self);
|
||||
|
||||
parent->rb_nodes[which] = new_self->rb_left;
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
|
||||
} else {
|
||||
/*
|
||||
* New self has one child. And we know it's on the
|
||||
* opposite side than what we want. So we want to
|
||||
* replace new_self with it and then self with new_self.
|
||||
*/
|
||||
which = new_self->rb_position;
|
||||
parent = new_self->rb_nodes[which ^ RB_OTHER];
|
||||
was_black = RB_BLACK_P(parent);
|
||||
|
||||
KASSERT(RB_SENTINEL_P(new_self->rb_nodes[which]));
|
||||
KASSERT(!RB_SENTINEL_P(parent));
|
||||
KASSERT(RB_CHILDLESS_P(parent));
|
||||
|
||||
/*
|
||||
* Move parent to new_self's location in the tree.
|
||||
*/
|
||||
new_self->rb_parent->rb_nodes[new_self->rb_position] = parent;
|
||||
parent->rb_parent = new_self->rb_parent;
|
||||
parent->rb_properties = new_self->rb_properties;
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
|
||||
}
|
||||
|
||||
/*
|
||||
* Move new_self to our location in the tree.
|
||||
*/
|
||||
self->rb_parent->rb_nodes[self->rb_position] = new_self;
|
||||
new_self->rb_left = self->rb_left;
|
||||
new_self->rb_right = self->rb_right;
|
||||
new_self->rb_parent = self->rb_parent;
|
||||
new_self->rb_properties = self->rb_properties;
|
||||
new_self->rb_left->rb_parent = new_self;
|
||||
new_self->rb_right->rb_parent = new_self;
|
||||
KASSERT(rb_tree_check_node(rbt, new_self, NULL, false));
|
||||
|
||||
/*
|
||||
* Rebalance if the node was
|
||||
*/
|
||||
if (was_black)
|
||||
rb_tree_removal_rebalance(rbt, parent, which);
|
||||
}
|
||||
|
||||
done:
|
||||
/*
|
||||
* Remove ourselves from the node list and decrement the count.
|
||||
*/
|
||||
TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
|
||||
rbt->rbt_count--;
|
||||
|
||||
if (child != NULL) {
|
||||
KASSERT(!child->rb_sentinel);
|
||||
#if 0
|
||||
(*rbt->rbt_print_node)(child, "before ");
|
||||
#endif
|
||||
rb_tree_removal_rebalance(rbt, child);
|
||||
#if 0
|
||||
(*rbt->rbt_print_node)(child, "after ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *self)
|
||||
rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *parent,
|
||||
unsigned int which)
|
||||
{
|
||||
KASSERT(!RB_SENTINEL_P(parent));
|
||||
KASSERT(RB_SENTINEL_P(parent->rb_nodes[which]));
|
||||
|
||||
while (RB_BLACK_P(parent->rb_nodes[which])) {
|
||||
unsigned int other = which ^ RB_OTHER;
|
||||
struct rb_node *brother = parent->rb_nodes[other];
|
||||
|
||||
KASSERT(!RB_SENTINEL_P(brother));
|
||||
/*
|
||||
* For cases 1, 2a, and 2b, our brother's children must
|
||||
* be black.
|
||||
*/
|
||||
if (RB_BLACK_P(brother->rb_left)
|
||||
&& RB_BLACK_P(brother->rb_right)) {
|
||||
/*
|
||||
* Case 1: Our brother is red, swap its position
|
||||
* (and colors) with our parent. This is now case 2b.
|
||||
*
|
||||
* B -> D
|
||||
* x d -> b E
|
||||
* C E -> x C
|
||||
*/
|
||||
if (RB_RED_P(brother)) {
|
||||
KASSERT(RB_BLACK_P(parent));
|
||||
rb_tree_swap_nodes(rbt, parent, other);
|
||||
brother = parent->rb_nodes[other];
|
||||
KASSERT(RB_BLACK_P(parent->rb_nodes[which]));
|
||||
KASSERT(!RB_SENTINEL_P(brother));
|
||||
KASSERT(RB_RED_P(parent));
|
||||
KASSERT(RB_BLACK_P(brother->rb_left)
|
||||
&& RB_BLACK_P(brother->rb_right));
|
||||
}
|
||||
if (RB_BLACK_P(parent)) {
|
||||
/*
|
||||
* Both our parent and brother are black.
|
||||
* Change our brother to red, advance up rank
|
||||
* and go through the loop again.
|
||||
*
|
||||
* B -> B
|
||||
* A D -> A d
|
||||
* C E -> C E
|
||||
*/
|
||||
RB_MARK_RED(brother);
|
||||
if (RB_ROOT_P(parent))
|
||||
return;
|
||||
KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
|
||||
which = parent->rb_position;
|
||||
parent = parent->rb_parent;
|
||||
} else {
|
||||
KASSERT(RB_BLACK_P(brother));
|
||||
RB_MARK_BLACK(parent);
|
||||
RB_MARK_RED(brother);
|
||||
KASSERT(rb_tree_check_node(rbt, brother, NULL, true));
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
KASSERT(RB_BLACK_P(brother));
|
||||
KASSERT(!RB_CHILDLESS_P(brother));
|
||||
/*
|
||||
* Case 3: our brother is black, our left nephew is
|
||||
* red, and our right nephew is black. Swap our
|
||||
* brother with our left nephew. This result in a
|
||||
* tree that matches case 4.
|
||||
*
|
||||
* B -> D
|
||||
* A D -> B E
|
||||
* c e -> A C
|
||||
*/
|
||||
if (RB_BLACK_P(brother->rb_nodes[other])) {
|
||||
KASSERT(RB_RED_P(brother->rb_nodes[which]));
|
||||
rb_tree_swap_nodes(rbt, brother, which);
|
||||
brother = parent->rb_nodes[other];
|
||||
KASSERT(RB_RED_P(brother->rb_nodes[other]));
|
||||
}
|
||||
/*
|
||||
* Case 4: our brother is black and our right nephew
|
||||
* is red. Swap our parent and brother locations and
|
||||
* change our right nephew to black. (these can be
|
||||
* done in either order so we change the color first).
|
||||
* The result is a valid red-black tree and is a
|
||||
* terminal case.
|
||||
*
|
||||
* B -> D
|
||||
* A D -> B E
|
||||
* c e -> A C
|
||||
*/
|
||||
RB_MARK_BLACK(brother->rb_nodes[other]);
|
||||
rb_tree_swap_nodes(rbt, parent, other);
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
|
||||
return;
|
||||
}
|
||||
}
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool
|
||||
rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self,
|
||||
const struct rb_node *prev, bool red_check)
|
||||
{
|
||||
KASSERT(!self->rb_sentinel);
|
||||
while (self->rb_parent != NULL && !self->rb_red) {
|
||||
struct rb_node *parent = self->rb_parent;
|
||||
int which = (self == parent->rb_left) ? RB_LEFT : RB_RIGHT;
|
||||
int other = which ^ RB_OTHER;
|
||||
struct rb_node *sibling = parent->rb_nodes[other];
|
||||
KASSERT(self->rb_left);
|
||||
KASSERT(self->rb_right);
|
||||
KASSERT(prev == NULL || (*rbt->rbt_compare_nodes)(prev, self) > 0);
|
||||
|
||||
if (sibling->rb_red) {
|
||||
sibling->rb_red = 0;
|
||||
parent->rb_red = 1;
|
||||
rb_tree_rotate(rbt, parent, which);
|
||||
parent = self->rb_parent;
|
||||
sibling = parent->rb_nodes[other];
|
||||
/*
|
||||
* Verify our relationship to our parent.
|
||||
*/
|
||||
if (RB_ROOT_P(self)) {
|
||||
KASSERT(self == rbt->rbt_root);
|
||||
KASSERT(self->rb_position == RB_LEFT);
|
||||
KASSERT(self->rb_parent->rb_nodes[RB_LEFT] == self);
|
||||
KASSERT(self->rb_parent == (const struct rb_node *) &rbt->rbt_root);
|
||||
} else {
|
||||
KASSERT(self != rbt->rbt_root);
|
||||
KASSERT(!RB_PARENT_SENTINEL_P(self));
|
||||
if (self->rb_position == RB_LEFT) {
|
||||
KASSERT((*rbt->rbt_compare_nodes)(self, self->rb_parent) > 0);
|
||||
KASSERT(self->rb_parent->rb_nodes[RB_LEFT] == self);
|
||||
} else {
|
||||
KASSERT((*rbt->rbt_compare_nodes)(self, self->rb_parent) < 0);
|
||||
KASSERT(self->rb_parent->rb_nodes[RB_RIGHT] == self);
|
||||
}
|
||||
}
|
||||
|
||||
if (sibling->rb_sentinel ||
|
||||
(!sibling->rb_left->rb_red && !sibling->rb_right->rb_red)) {
|
||||
sibling->rb_red = 1;
|
||||
self = parent;
|
||||
continue;
|
||||
/*
|
||||
* The root must be black.
|
||||
* There can never be two adjacent red nodes.
|
||||
*/
|
||||
if (red_check) {
|
||||
KASSERT(!RB_ROOT_P(self) || RB_BLACK_P(self));
|
||||
if (RB_RED_P(self)) {
|
||||
KASSERT(!RB_ROOT_P(self));
|
||||
KASSERT(RB_BLACK_P(self->rb_parent));
|
||||
KASSERT(RB_LEFT_SENTINEL_P(self)
|
||||
|| RB_BLACK_P(self->rb_left));
|
||||
KASSERT(RB_RIGHT_SENTINEL_P(self)
|
||||
|| RB_BLACK_P(self->rb_right));
|
||||
}
|
||||
/*
|
||||
* A grandparent's children must be real nodes and not
|
||||
* sentinels. First check out grandparent.
|
||||
*/
|
||||
KASSERT(RB_ROOT_P(self)
|
||||
|| RB_ROOT_P(self->rb_parent)
|
||||
|| RB_TWOCHILDREN_P(self->rb_parent->rb_parent));
|
||||
/*
|
||||
* If we are have grandchildren on our left, then
|
||||
* we must have a child on our right.
|
||||
*/
|
||||
KASSERT(RB_LEFT_SENTINEL_P(self)
|
||||
|| RB_CHILDLESS_P(self->rb_left)
|
||||
|| !RB_RIGHT_SENTINEL_P(self));
|
||||
/*
|
||||
* If we are have grandchildren on our right, then
|
||||
* we must have a child on our left.
|
||||
*/
|
||||
KASSERT(RB_RIGHT_SENTINEL_P(self)
|
||||
|| RB_CHILDLESS_P(self->rb_right)
|
||||
|| !RB_LEFT_SENTINEL_P(self));
|
||||
}
|
||||
|
||||
if (!sibling->rb_nodes[other]->rb_red) {
|
||||
sibling->rb_nodes[which]->rb_red = 0;
|
||||
sibling->rb_red = 1;
|
||||
rb_tree_rotate(rbt, sibling, other);
|
||||
parent = self->rb_parent;
|
||||
sibling = parent->rb_nodes[other];
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rb_tree_check(const struct rb_tree *rbt, bool red_check)
|
||||
{
|
||||
const struct rb_node *self;
|
||||
const struct rb_node *prev;
|
||||
int counts[2] = { 0, 0 };
|
||||
unsigned int which = RB_LEFT;
|
||||
|
||||
KASSERT(rbt->rbt_root == NULL || rbt->rbt_root->rb_position == RB_LEFT);
|
||||
|
||||
prev = NULL;
|
||||
TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
|
||||
rb_tree_check_node(rbt, self, prev, false);
|
||||
if (self == rbt->rbt_root) {
|
||||
which = RB_RIGHT;
|
||||
} else {
|
||||
counts[which]++;
|
||||
}
|
||||
prev = self;
|
||||
}
|
||||
KASSERT(rbt->rbt_count == counts[RB_RIGHT] + counts[RB_LEFT] + (which == RB_RIGHT));
|
||||
|
||||
sibling->rb_red = parent->rb_red;
|
||||
parent->rb_red = 0;
|
||||
sibling->rb_nodes[other]->rb_red = 0;
|
||||
rb_tree_rotate(rbt, parent, which);
|
||||
break;
|
||||
/*
|
||||
* The root must be black.
|
||||
* There can never be two adjacent red nodes.
|
||||
*/
|
||||
if (red_check) {
|
||||
KASSERT(rbt->rbt_root == NULL || RB_BLACK_P(rbt->rbt_root));
|
||||
TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
|
||||
rb_tree_check_node(rbt, self, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rb.h,v 1.2 2002/10/08 11:58:54 simonb Exp $ */
|
||||
/* $NetBSD: rb.h,v 1.3 2006/09/05 04:35:45 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
struct rb_node {
|
||||
struct rb_node *rb_nodes[3];
|
||||
|
@ -51,10 +52,44 @@ struct rb_node {
|
|||
#define rb_right rb_nodes[RB_RIGHT]
|
||||
#define rb_parent rb_nodes[RB_PARENT]
|
||||
TAILQ_ENTRY(rb_node) rb_link;
|
||||
int rb_balance : 16;
|
||||
unsigned int rb_red : 1;
|
||||
unsigned int rb_sentinel : 1;
|
||||
unsigned int rb_position : 2;
|
||||
union {
|
||||
struct {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
unsigned int : 27;
|
||||
unsigned int s_root : 1;
|
||||
unsigned int s_position : 2;
|
||||
unsigned int s_color : 1;
|
||||
unsigned int s_sentinel : 1;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
unsigned int s_sentinel : 1;
|
||||
unsigned int s_color : 1;
|
||||
unsigned int s_position : 2;
|
||||
unsigned int s_root : 1;
|
||||
unsigned int : 27;
|
||||
#endif
|
||||
} u_s;
|
||||
unsigned int u_i;
|
||||
} rb_u;
|
||||
#define rb_root rb_u.u_s.s_root
|
||||
#define rb_position rb_u.u_s.s_position
|
||||
#define rb_color rb_u.u_s.s_color
|
||||
#define rb_sentinel rb_u.u_s.s_sentinel
|
||||
#define rb_properties rb_u.u_i
|
||||
#define RB_SENTINEL_P(rb) ((rb)->rb_sentinel + 0)
|
||||
#define RB_LEFT_SENTINEL_P(rb) ((rb)->rb_left->rb_sentinel + 0)
|
||||
#define RB_RIGHT_SENTINEL_P(rb) ((rb)->rb_right->rb_sentinel + 0)
|
||||
#define RB_PARENT_SENTINEL_P(rb) ((rb)->rb_parent->rb_sentinel + 0)
|
||||
#define RB_CHILDLESS_P(rb) (RB_LEFT_SENTINEL_P(rb) \
|
||||
&& RB_RIGHT_SENTINEL_P(rb))
|
||||
#define RB_TWOCHILDREN_P(rb) (!RB_LEFT_SENTINEL_P(rb) \
|
||||
&& !RB_RIGHT_SENTINEL_P(rb))
|
||||
#define RB_ROOT_P(rb) ((rb)->rb_root != false)
|
||||
#define RB_RED_P(rb) ((rb)->rb_color + 0)
|
||||
#define RB_BLACK_P(rb) (!(rb)->rb_color)
|
||||
#define RB_MARK_RED(rb) ((void)((rb)->rb_color = 1))
|
||||
#define RB_MARK_BLACK(rb) ((void)((rb)->rb_color = 0))
|
||||
#define RB_MARK_ROOT(rb) ((void)((rb)->rb_root = 1))
|
||||
};
|
||||
|
||||
TAILQ_HEAD(rb_node_qh, rb_node);
|
||||
|
@ -70,7 +105,7 @@ struct rb_tree {
|
|||
rb_compare_nodes_fn rbt_compare_nodes;
|
||||
rb_compare_key_fn rbt_compare_key;
|
||||
rb_print_node_fn rbt_print_node;
|
||||
u_int rbt_count;
|
||||
unsigned int rbt_count;
|
||||
};
|
||||
|
||||
void rb_tree_init(struct rb_tree *, rb_compare_nodes_fn, rb_compare_key_fn,
|
||||
|
@ -78,5 +113,6 @@ void rb_tree_init(struct rb_tree *, rb_compare_nodes_fn, rb_compare_key_fn,
|
|||
void rb_tree_insert_node(struct rb_tree *, struct rb_node *);
|
||||
struct rb_node *rb_tree_find(struct rb_tree *, void *);
|
||||
void rb_tree_remove_node(struct rb_tree *, struct rb_node *);
|
||||
void rb_tree_check(const struct rb_tree *, bool);
|
||||
|
||||
#endif /* _LIBKERN_RB_H_*/
|
||||
|
|
Loading…
Reference in New Issue