예제 #1
0
파일: avl.c 프로젝트: hubugui/ds
int avl_remove(struct avl *avl, void *value, compare cmp)
{
    struct avl_node *node, **parentp, *min, *left;

    if ((node = _node_search(avl, value, &parentp, cmp)) == NULL)
        return -1;

retry:
    /* leaf */
    if (!node->left && !node->right) {
        *parentp = NULL;
        goto rebalance;
    }
    /* single child */
    if (!node->left || !node->right) {
        *parentp = node->left ? node->left : node->right;
        (*parentp)->parent = node->parent;
        goto rebalance;
    }
    /* double child, find the min node from right subtree */
    for (left = node->right; left; left = min->left) {
        min = left;
    }
    _swap_value(node, min);
    /* now node only have 0 or 1 child */
    node = min;
    parentp = (node == node->parent->left) ?
              &node->parent->left : &node->parent->right;
    goto retry;

rebalance:
    _remove_rebalance(avl, node->parent, cmp);
    avl->count--;
    free(node);
    return 0;
}
예제 #2
0
파일: tree.c 프로젝트: rodrigobmg/v-engine
void Tree_remove(Tree _tree, var _key)
{
    struct tree_node *child, *parent, *old, *left, *node, *root = _tree->root;
    node_color color;
    var key;
    if (unlikely(!_tree->root))
    {
        return;
    }

    if (_tree->key_type != String)
    {
        key = _key;
    }
    else
    {
        key.str_var = EString_new((char*)_key.str_var);
    }
    if (!(node = _search_auxiliary(_tree, key, root, NULL)))
    {
        if (_tree->key_type == String)
        {
            EString_delete((char*)key.str_var);
        }
        return;
    }
    if (_tree->key_type == String)
    {
        EString_delete((char*)key.str_var);
    }
    old = node;
    if (node->left_node && node->right_node)
    {
        node = node->right_node;
        while ((left = node->left_node) != NULL)
        {
            node = left;
        }
        child = node->right_node;
        parent = node->parent_node;
        color = node->color;

        if (child)
        {
            child->parent_node = parent;
        }
        if (parent)
        {
            if (parent->left_node == node)
            {
                parent->left_node = child;
            }
            else
            {
                parent->right_node = child;
            }
        }
        else
        {
            root = child;
        }
        if (node->parent_node == old)
        {
            parent = node;
        }
        node->parent_node = old->parent_node;
        node->color = old->color;
        node->right_node = old->right_node;
        node->left_node = old->left_node;
        if (old->parent_node)
        {
            if (old->parent_node->left_node == old)
            {
                old->parent_node->left_node = node;
            }
            else
            {
                old->parent_node->right_node = node;
            }
        }
        else
        {
            root = node;
        }
        old->left_node->parent_node = node;
        if (old->right_node)
        {
            old->right_node->parent_node = node;
        }
    }
    else
    {
        if (!node->left_node)
        {
            child = node->right_node;
        }
        else if (!node->right_node)
        {
            child = node->left_node;
        }
        parent = node->parent_node;
        color = node->color;
        if (child)
        {
            child->parent_node = parent;
        }
        if (parent)
        {
            if (parent->left_node == node)
            {
                parent->left_node = child;
            }
            else
            {
                parent->right_node = child;
            }
        }
        else
        {
            root = child;
        }
    }
    if (old != _tree->head)
    {
        if (old != _tree->tail)
        {
            old->iter_prev->iter_next = old->iter_next;
            old->iter_next->iter_prev = old->iter_prev;
        }
        else
        {
            old->iter_prev->iter_next = NULL;
            _tree->tail = old->iter_prev;
        }
    }
    else
    {
        if (old != _tree->tail)
        {
            old->iter_next->iter_prev = NULL;
            _tree->head = old->iter_next;
        }
        else
        {
            _tree->root = _tree->head = _tree->tail = NULL;
            _tree->count = 0;
            return;
        }
    }
    _tree->count--;

    _tree->free_proc(old);
    if (color == Black)
    {
        root = _remove_rebalance(child, parent, root);
    }
    _tree->root = root;
}