예제 #1
0
파일: avl.c 프로젝트: const86/rfs
static bool remove(struct avl *t, void **pp, void **px)
{
	if (*pp == NULL) {
		*px = NULL;
		return false;
	}

	int cmp = t->cmp(*px, *pp);
	struct avl_node *p = node(t, *pp);
	bool dir, shrink;

	if (cmp == 0) {
		*px = *pp;
		dir = p->balance > 0;

		if (p->child[dir] == NULL) {
			*pp = p->child[!dir];
			return true;
		}

		void *swap;
		shrink = remove_swap(t, &p->child[dir], !dir, &swap);
		*node(t, swap) = *node(t, *pp);
		*pp = swap;
	} else {
		dir = cmp > 0;
		shrink = remove(t, &node(t, *pp)->child[dir], px);
	}

	return remove_fix(t, pp, dir, shrink);
}
예제 #2
0
파일: avl.c 프로젝트: const86/rfs
static bool remove_swap(struct avl *t, void **pp, bool dir, void **swap)
{
	struct avl_node *p = node(t, *pp);

	if (p->child[dir] == NULL) {
		*swap = *pp;
		*pp = p->child[!dir];
		return true;
	}

	bool shrink = remove_swap(t, &p->child[dir], dir, swap);
	return remove_fix(t, pp, dir, shrink);
}
예제 #3
0
bool rbtree_remove(RBTree *tree, const void *key)
{
    assert(!tree->nil->red);

    RBNode *z = node_get(tree, key);
    if (z == tree->nil)
    {
        return false;
    }

    RBNode *y = ((z->left == tree->nil) || (z->right == tree->nil)) ? z : node_next(tree, z);
    RBNode *x = (y->left == tree->nil) ? y->right : y->left;

    x->parent = y->parent;
    if (tree->root == x->parent)
    {
        tree->root->left = x;
    }
    else
    {
        if (y == y->parent->left)
        {
            y->parent->left = x;
        }
        else
        {
            y->parent->right = x;
        }
    }

    if (z != y)
    {
        assert(y != tree->nil);
        assert(!tree->nil->red);

        if (!y->red)
        {
            remove_fix(tree, x);
        }

        y->left = z->left;
        y->right = z->right;
        y->parent = z->parent;
        y->red = z->red;
        z->left->parent = y;
        z->right->parent = y;

        if (z == z->parent->left)
        {
            z->parent->left = y;
        }
        else
        {
            z->parent->right = y;
        }
        node_destroy(tree, z);
    }
    else
    {
        if (!y->red)
        {
            remove_fix(tree, x);
        }
        node_destroy(tree, y);
    }

    assert(!tree->nil->red);

    tree->size--;
    return true;
}