337 lines
6.2 KiB
C
337 lines
6.2 KiB
C
#include <stddef.h>
|
|
#include "ucore_rbtree.h"
|
|
//modified from generated code of tree.h
|
|
|
|
static void
|
|
rotateleft(RBTree *root, RBNode *node)
|
|
{
|
|
RBNode *right = node->right;
|
|
|
|
node->right = right->left;
|
|
if (right->left)
|
|
right->left->parent = node;
|
|
right->left = node;
|
|
|
|
right->parent = node->parent;
|
|
if (node->parent) {
|
|
if (node == node->parent->left)
|
|
node->parent->left = right;
|
|
else
|
|
node->parent->right = right;
|
|
} else
|
|
root->node = right;
|
|
node->parent = right;
|
|
}
|
|
|
|
static void
|
|
rotateright(RBTree *root, RBNode *node)
|
|
{
|
|
RBNode *left = node->left;
|
|
|
|
node->left = left->right;
|
|
if (left->right)
|
|
left->right->parent = node;
|
|
left->right = node;
|
|
|
|
left->parent = node->parent;
|
|
if (node->parent) {
|
|
if (node == node->parent->right)
|
|
node->parent->right = left;
|
|
else
|
|
node->parent->left = left;
|
|
} else
|
|
root->node = left;
|
|
node->parent = left;
|
|
}
|
|
|
|
static void
|
|
rb_insertcolor(RBTree *root, RBNode *node)
|
|
{
|
|
RBNode *parent, *gparent;
|
|
|
|
while ((parent = node->parent) && parent->color == Red) {
|
|
gparent = parent->parent;
|
|
|
|
if (parent == gparent->left) {
|
|
RBNode *uncle = gparent->right;
|
|
if (uncle && uncle->color == Red) {
|
|
uncle->color = Black;
|
|
parent->color = Black;
|
|
gparent->color = Red;
|
|
node = gparent;
|
|
continue;
|
|
}
|
|
|
|
if (parent->right == node) {
|
|
RBNode *tmp;
|
|
rotateleft(root, parent);
|
|
tmp = parent;
|
|
parent = node;
|
|
node = tmp;
|
|
}
|
|
|
|
parent->color = Black;
|
|
gparent->color = Red;
|
|
rotateright(root, gparent);
|
|
}
|
|
|
|
else {
|
|
RBNode *uncle = gparent->left;
|
|
if (uncle && uncle->color == Red) {
|
|
uncle->color = Black;
|
|
parent->color = Black;
|
|
gparent->color = Red;
|
|
node = gparent;
|
|
continue;
|
|
}
|
|
|
|
if (parent->left == node) {
|
|
RBNode *tmp;
|
|
rotateright(root, parent);
|
|
tmp = parent;
|
|
parent = node;
|
|
node = tmp;
|
|
}
|
|
|
|
parent->color = Black;
|
|
gparent->color = Red;
|
|
rotateleft(root, gparent);
|
|
}
|
|
}
|
|
|
|
root->node->color = Black;
|
|
}
|
|
|
|
static void
|
|
removecolor(RBTree *root, RBNode *node, RBNode *parent)
|
|
{
|
|
RBNode *other;
|
|
|
|
while ((!node || node->color == Black) && node != root->node) {
|
|
if (parent->left == node) {
|
|
other = parent->right;
|
|
if (other->color == Red) {
|
|
other->color = Black;
|
|
parent->color = Red;
|
|
rotateleft(root, parent);
|
|
other = parent->right;
|
|
}
|
|
if ((!other->left || other->left->color == Black)
|
|
&& (!other->right
|
|
|| other->right->color == Black)) {
|
|
other->color = Red;
|
|
node = parent;
|
|
parent = node->parent;
|
|
} else {
|
|
if (!other->right
|
|
|| other->right->color == Black) {
|
|
RBNode *o_left;
|
|
if ((o_left = other->left))
|
|
o_left->color = Black;
|
|
other->color = Red;
|
|
rotateright(root, other);
|
|
other = parent->right;
|
|
}
|
|
other->color = parent->color;
|
|
parent->color = Black;
|
|
if (other->right)
|
|
other->right->color = Black;
|
|
rotateleft(root, parent);
|
|
node = root->node;
|
|
break;
|
|
}
|
|
}
|
|
|
|
else {
|
|
other = parent->left;
|
|
if (other->color == Red) {
|
|
other->color = Black;
|
|
parent->color = Red;
|
|
rotateright(root, parent);
|
|
other = parent->left;
|
|
}
|
|
if ((!other->left || other->left->color == Black)
|
|
&& (!other->right
|
|
|| other->right->color == Black)) {
|
|
other->color = Red;
|
|
node = parent;
|
|
parent = node->parent;
|
|
} else {
|
|
if (!other->left
|
|
|| other->left->color == Black) {
|
|
RBNode *o_right;
|
|
if ((o_right = other->right))
|
|
o_right->color = Black;
|
|
other->color = Red;
|
|
rotateleft(root, other);
|
|
other = parent->left;
|
|
}
|
|
other->color = parent->color;
|
|
parent->color = Black;
|
|
if (other->left)
|
|
other->left->color = Black;
|
|
rotateright(root, parent);
|
|
node = root->node;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (node)
|
|
node->color = Black;
|
|
}
|
|
|
|
void
|
|
uc_rb_remove(RBTree *root, RBNode *node)
|
|
{
|
|
RBNode *child, *parent;
|
|
int color;
|
|
|
|
if (!node->left)
|
|
child = node->right;
|
|
else if (!node->right)
|
|
child = node->left;
|
|
else {
|
|
RBNode *old = node, *left;
|
|
|
|
node = node->right;
|
|
while ((left = node->left))
|
|
node = left;
|
|
child = node->right;
|
|
parent = node->parent;
|
|
color = node->color;
|
|
|
|
if (child)
|
|
child->parent = parent;
|
|
if (parent) {
|
|
if (parent->left == node)
|
|
parent->left = child;
|
|
else
|
|
parent->right = child;
|
|
} else
|
|
root->node = child;
|
|
|
|
if (node->parent == old)
|
|
parent = node;
|
|
node->parent = old->parent;
|
|
node->color = old->color;
|
|
node->right = old->right;
|
|
node->left = old->left;
|
|
|
|
if (old->parent) {
|
|
if (old->parent->left == old)
|
|
old->parent->left = node;
|
|
else
|
|
old->parent->right = node;
|
|
} else
|
|
root->node = node;
|
|
|
|
old->left->parent = node;
|
|
if (old->right)
|
|
old->right->parent = node;
|
|
goto finish;
|
|
}
|
|
|
|
parent = node->parent;
|
|
color = node->color;
|
|
|
|
if (child)
|
|
child->parent = parent;
|
|
if (parent) {
|
|
if (parent->left == node)
|
|
parent->left = child;
|
|
else
|
|
parent->right = child;
|
|
} else
|
|
root->node = child;
|
|
|
|
finish:
|
|
if (color == Black)
|
|
removecolor(root, child, parent);
|
|
}
|
|
|
|
RBNode*
|
|
uc_rb_find(RBTree *root, const void *val)
|
|
{
|
|
RBNode *n = root->node;
|
|
while (n) {
|
|
int d = root->compare(val,n->data);
|
|
if (d < 0)
|
|
n = n->left;
|
|
else if (d > 0)
|
|
n = n->right;
|
|
else
|
|
return n;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
RBNode*
|
|
uc_rb_insert(RBTree *root, RBNode *child)
|
|
{
|
|
RBNode **p = &root->node;
|
|
RBNode *parent = NULL;
|
|
int d;
|
|
while (*p) {
|
|
parent = *p;
|
|
d = root->compare(child->data, parent->data);
|
|
if (d < 0)
|
|
p = &(*p)->left;
|
|
else if (d > 0)
|
|
p = &(*p)->right;
|
|
else
|
|
return parent;
|
|
}
|
|
|
|
child->parent = parent;
|
|
child->color = Red;
|
|
child->left = child->right = NULL;
|
|
*p = child;
|
|
rb_insertcolor(root, child);
|
|
return NULL;
|
|
}
|
|
|
|
RBNode *uc_rb_first(const RBTree *root)
|
|
{
|
|
RBNode *n = root->node;
|
|
if(n == NULL)
|
|
return NULL;
|
|
|
|
while(n->left)
|
|
n = n->left;
|
|
|
|
return n;
|
|
}
|
|
|
|
RBNode *uc_rb_next(RBNode *node)
|
|
{
|
|
if(node->right) { //down and left of the right branch
|
|
node = node->right;
|
|
|
|
while(node->left)
|
|
node = node->left;
|
|
|
|
} else { //up until we are not the right node
|
|
|
|
while(node->parent && node == node->parent->right)
|
|
node = node->parent;
|
|
|
|
node = node->parent;
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
RBNode *uc_rb_last(const RBTree *root)
|
|
{
|
|
RBNode *n = root->node;
|
|
|
|
if(n == NULL)
|
|
return NULL;
|
|
|
|
while(n->right)
|
|
n = n->right;
|
|
|
|
return n;
|
|
}
|