Example #1
0
static void destroy_subtree(AvlTree *tree, AvlNode **subtree_root)
{
	if ((*subtree_root) == 0)
		return;

	AvlNode *this_node = (*subtree_root);

	while (TRUE)
		if (this_node->links.right)
			this_node = this_node->links.right;
		else
			if (this_node->links.left)
				this_node = this_node->links.left;
			else
			{
				AvlNode *node_to_delete = this_node;
				this_node = this_node->links.parent;

				free_avl_node(node_to_delete, tree->destroyKey);

				if (node_to_delete == (*subtree_root) || this_node == 0)
					break;
				else
					if (node_to_delete == this_node->links.right)
						this_node->links.right = 0;
					else
						this_node->links.left = 0;
			}

	(*subtree_root) = 0;
}
Example #2
0
VALUE_TYPE delete_node(AvlTree *tree, const KEY_TYPE key)
{
	AvlNode *parent_node = 0;
	AvlNode *this_node = *search_routine(key, &tree->tree_root, &parent_node, tree->compareKeys);

	if (this_node)
	{
		VALUE_TYPE res = this_node->value;

		rebalance_shrunk(this_node, &tree->tree_root);
		free_avl_node(this_node, tree->destroyKey);

		return res;
	}
	else
		return 0;
}
/*
 * used to recursively destroy (free up) all nodes below 'node'
 */
static void 
avl_node_destroy_nodes (avl_tree_t *tree,
        avl_node_t *node, 
        int leave_parent_consistent)
{
    avl_node_t *parent, *left, *right;

    // end node
    if (NULL == node) return;

    left = node->left;
    right = node->right;

    if (leave_parent_consistent) {
        parent = node->parent;
        if (parent) {
            if (parent->left == node) {
                parent->left = NULL;
            } else if (parent->right == node) {
                parent->right = NULL;
            } else {
                assert(0);
            }
        } else {
            tree->root_node = NULL;
        }
    }

    // done with this one.  Freeing this here before we get deep into
    // recursion frees up the nodes much more quickly without building
    // up all the stack of nodes during recursion.
    //
    free_avl_node(tree, node);

    // recurse on; since we will be deleting all these
    // nodes, there is no need to leave the parent's
    // pointers consistent.
    //
    avl_node_destroy_nodes(tree, left, 0);
    avl_node_destroy_nodes(tree, right, 0);
}
static int 
thread_unsafe_avl_tree_remove (avl_tree_t *tree,
        void *data_to_be_removed,
        void **actual_data_removed)
{
    avl_node_t *node, *to_be_deleted;
    avl_node_t *parent, *unbalanced;
    avl_node_t *left;
    avl_node_t *right;
    avl_node_t *next;
    int is_left;

    /* being traversed, cannot access */
    if (tree->cannot_be_modified) return EBUSY;

    /* find the matching node first */
    node = avl_lookup_engine(tree, data_to_be_removed,
            &parent, &unbalanced, &is_left);

    /* not there */
    if (!node) {
        *actual_data_removed = NULL;
        return ENODATA;
    }

    /* if we are here, we found it */
    *actual_data_removed = node->user_data;

    /* cache it for later freeing */
    to_be_deleted = node;

    parent = node->parent;
    left = node->left;
    right = node->right;

#if 0
    if (node == tree->first_node)
        tree->first_node = avl_tree_next(node);
    if (node == tree->last_node)
        tree->last_node = avl_tree_prev(node);
#endif

    if (!left)
        next = right;
    else if (!right)
        next = left;
    else
        next = get_first(right);

    if (parent) {
        is_left = (parent->left == node);
        set_child(next, parent, is_left);
    } else
        tree->root_node = next;

    if (left && right) {
        next->balance = node->balance;
        next->left = left;
        left->parent = next;
        if (next != right) {
            parent = next->parent;
            next->parent = node->parent;
            node = next->right;
            parent->left = node;
            next->right = right;
            right->parent = next;
            is_left = 1;
        } else {
            next->parent = parent;
            parent = next;
            node = parent->right;
            is_left = 0;
        }
        assert(parent != NULL);
    } else
        node = next;

    if (node)
        node->parent = parent;

    while (parent) {

        int balance;
            
        node = parent;
        parent = parent->parent;
        if (is_left) {
            is_left = (parent && (parent->left == node));
            balance = ++node->balance;
            if (balance == 0)           /* case 1 */
                continue;
            if (balance == 1) {         /* case 2 */
                goto END_OF_DELETE;
            }
            right = node->right;
            switch (right->balance) {
            case 0:                             /* case 3.1 */
                node->balance = 1;
                right->balance = -1;
                rotate_left(node, tree);
                goto END_OF_DELETE;
            case 1:                             /* case 3.2 */
                node->balance = 0;
                right->balance = 0;
                break;
            case -1:                    /* case 3.3 */
                switch (right->left->balance) {
                case 1:
                    node->balance = -1;
                    right->balance = 0;
                    break;
                case 0:
                    node->balance = 0;
                    right->balance = 0;
                    break;
                case -1:
                    node->balance = 0;
                    right->balance = 1;
                    break;
                }
                right->left->balance = 0;
                rotate_right(right, tree);
            }
            rotate_left(node, tree);
        } else {
            is_left = (parent && (parent->left == node));
            balance = --node->balance;
            if (balance == 0)
                continue;
            if (balance == -1) {
                goto END_OF_DELETE;
            }
            left = node->left;
            switch (left->balance) {
            case 0:
                node->balance = -1;
                left->balance = 1;
                rotate_right(node, tree);
                goto END_OF_DELETE;
            case -1:
                node->balance = 0;
                left->balance = 0;
                break;
            case 1:
                switch (left->right->balance) {
                case 1:
                    node->balance = 0;
                    left->balance = -1;
                    break;
                case 0:
                    node->balance = 0;
                    left->balance = 0;
                    break;
                case -1:
                    node->balance = 1;
                    left->balance = 0;
                    break;
                }
                left->right->balance = 0;
                rotate_left(left, tree);
            }
            rotate_right(node, tree);
        }
    }

END_OF_DELETE:
                
    free_avl_node(tree, to_be_deleted);
    if (tree->n <= 0) {
        assert(tree->root_node == NULL);
    } else {
        assert(tree->root_node != NULL);
    }
    return 0;
}