2022-08-04 11:40:24 +08:00

141 lines
2.9 KiB
C

#include "arm11/util/rbtree.h"
#include "rbtree_internal.h"
static void
recolor(rbtree_t *tree,
rbtree_node_t *parent,
rbtree_node_t *node)
{
rbtree_node_t *sibling;
while(is_black(node) && node != tree->root)
{
int left = (node == parent->child[LEFT]);
sibling = parent->child[left];
if(is_red(sibling))
{
set_black(sibling);
set_red(parent);
rbtree_rotate(tree, parent, left);
sibling = parent->child[left];
}
if(is_black(sibling->child[LEFT]) && is_black(sibling->child[RIGHT]))
{
set_red(sibling);
node = parent;
parent = get_parent(node);
}
else
{
if(is_black(sibling->child[left]))
{
set_black(sibling->child[!left]);
set_red(sibling);
rbtree_rotate(tree, sibling, !left);
sibling = parent->child[left];
}
if(is_black(parent))
set_black(sibling);
else
set_red(sibling);
set_black(parent);
set_black(sibling->child[left]);
rbtree_rotate(tree, parent, left);
node = tree->root;
}
}
if(node != NULL)
set_black(node);
}
rbtree_node_t*
rbtree_remove(rbtree_t *tree,
rbtree_node_t *node,
rbtree_node_destructor_t destructor)
{
rbtree_color_t color;
rbtree_node_t *child, *parent, *original = node;
rbtree_node_t *next;
next = rbtree_node_next(node);
if(node->child[LEFT] != NULL && node->child[RIGHT] != NULL)
{
rbtree_node_t *old = node;
node = node->child[RIGHT];
while(node->child[LEFT] != NULL)
node = node->child[LEFT];
parent = get_parent(old);
if(parent != NULL)
{
if(parent->child[LEFT] == old)
parent->child[LEFT] = node;
else
parent->child[RIGHT] = node;
}
else
tree->root = node;
child = node->child[RIGHT];
parent = get_parent(node);
color = get_color(node);
if(parent == old)
parent = node;
else
{
if(child != NULL)
set_parent(child, parent);
parent->child[LEFT] = child;
node->child[RIGHT] = old->child[RIGHT];
set_parent(old->child[RIGHT], node);
}
node->parent_color = old->parent_color;
node->child[LEFT] = old->child[LEFT];
set_parent(old->child[LEFT], node);
}
else
{
if(node->child[LEFT] == NULL)
child = node->child[RIGHT];
else
child = node->child[LEFT];
parent = get_parent(node);
color = get_color(node);
if(child != NULL)
set_parent(child, parent);
if(parent != NULL)
{
if(parent->child[LEFT] == node)
parent->child[LEFT] = child;
else
parent->child[RIGHT] = child;
}
else
tree->root = child;
}
if(color == BLACK)
recolor(tree, parent, child);
if(destructor != NULL)
(*destructor)(original);
tree->size -= 1;
return next;
}