mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-07 06:14:12 +08:00
97 lines
1.7 KiB
C
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);
|
|
}
|