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

97 lines
1.7 KiB
C

#include "arm11/util/rbtree.h"
#include "rbtree_internal.h"
static rbtree_node_t*
do_insert(rbtree_t *tree,
rbtree_node_t *node,
int multi)
{
rbtree_node_t *original = node;
rbtree_node_t **tmp = &tree->root;
rbtree_node_t *parent = NULL;
rbtree_node_t *save = NULL;
while(*tmp != NULL)
{
int cmp = (*(tree->comparator))(node, *tmp);
parent = *tmp;
if(cmp < 0)
tmp = &((*tmp)->child[LEFT]);
else if(cmp > 0)
tmp = &((*tmp)->child[RIGHT]);
else
{
if(!multi)
save = *tmp;
tmp = &((*tmp)->child[LEFT]);
}
}
if(save != NULL)
{
return save;
}
*tmp = node;
node->child[LEFT] = node->child[RIGHT] = NULL;
set_parent(node, parent);
set_red(node);
while(is_red((parent = get_parent(node))))
{
rbtree_node_t *grandparent = get_parent(parent);
int left = (parent == grandparent->child[LEFT]);
rbtree_node_t *uncle = grandparent->child[left];
if(is_red(uncle))
{
set_black(uncle);
set_black(parent);
set_red(grandparent);
node = grandparent;
}
else
{
if(parent->child[left] == node)
{
rbtree_node_t *tmp;
rbtree_rotate(tree, parent, left);
tmp = parent;
parent = node;
node = tmp;
}
set_black(parent);
set_red(grandparent);
rbtree_rotate(tree, grandparent, !left);
}
}
set_black(tree->root);
tree->size += 1;
return original;
}
rbtree_node_t*
rbtree_insert(rbtree_t *tree,
rbtree_node_t *node)
{
return do_insert(tree, node, 0);
}
void
rbtree_insert_multi(rbtree_t *tree,
rbtree_node_t *node)
{
do_insert(tree, node, 1);
}