Beispiel #1
0
/*
 * Template for performing a double rotation ---
 *
 * sign > 0:  Rotate counterclockwise (left) rooted at B, then
 *		     clockwise (right) rooted at A:
 *
 *           P?            P?          P?
 *           |             |           |
 *           A             A           E
 *          / \           / \        /   \
 *         B   C?  =>    E   C? =>  B     A
 *        / \           / \        / \   / \
 *       D?  E         B   G?     D?  F?G?  C?
 *          / \       / \
 *         F?  G?    D?  F?
 *
 * (nodes marked with ? may not exist)
 *
 * sign < 0:  Rotate clockwise (right) rooted at B, then
 *		     counterclockwise (left) rooted at A:
 *
 *         P?          P?              P?
 *         |           |               |
 *         A           A               E
 *        / \         / \            /   \
 *       C?  B   =>  C?  E    =>    A     B
 *          / \         / \        / \   / \
 *         E   D?      G?  B      C?  G?F?  D?
 *        / \             / \
 *       G?  F?          F?  D?
 *
 * Returns a pointer to E and updates balance factors.  Except for those
 * two things, this function is equivalent to:
 *	avl_rotate(root_ptr, B, -sign);
 *	avl_rotate(root_ptr, A, +sign);
 *
 * See comment in avl_handle_subtree_growth() for explanation of balance
 * factor updates.
 */
static AVL_INLINE struct avl_tree_node *
avl_do_double_rotate(struct avl_tree_node ** const root_ptr,
		     struct avl_tree_node * const B,
		     struct avl_tree_node * const A, const int sign)
{
	struct avl_tree_node * const E = avl_get_child(B, +sign);
	struct avl_tree_node * const F = avl_get_child(E, -sign);
	struct avl_tree_node * const G = avl_get_child(E, +sign);
	struct avl_tree_node * const P = avl_get_parent(A);
	const int e = avl_get_balance_factor(E);

	avl_set_child(A, -sign, G);
	avl_set_parent_balance(A, E, ((sign * e >= 0) ? 0 : -e));

	avl_set_child(B, +sign, F);
	avl_set_parent_balance(B, E, ((sign * e <= 0) ? 0 : -e));

	avl_set_child(E, +sign, A);
	avl_set_child(E, -sign, B);
	avl_set_parent_balance(E, P, 0);

	if (G)
		avl_set_parent(G, A);

	if (F)
		avl_set_parent(F, B);

	avl_replace_child(root_ptr, P, A, E);

	return E;
}
Beispiel #2
0
/*
 * Removes an item from the specified AVL tree.
 *
 * @root_ptr
 *	Location of the AVL tree's root pointer.  Indirection is needed
 *	because the root node may change if the tree needed to be rebalanced
 *	because of the deletion or if @node was the root node.
 *
 * @node
 *	Pointer to the `struct avl_tree_node' embedded in the item to
 *	remove from the tree.
 *
 * Note: This function *only* removes the node and rebalances the tree.
 * It does not free any memory, nor does it do the equivalent of
 * avl_tree_node_set_unlinked().
 */
void
avl_tree_remove(struct avl_tree_node **root_ptr, struct avl_tree_node *node)
{
	struct avl_tree_node *parent;
	bool left_deleted = false;

	if (node->left && node->right) {
		/* @node is fully internal, with two children.  Swap it
		 * with its in-order successor (which must exist in the
		 * right subtree of @node and can have, at most, a right
		 * child), then unlink @node.  */
		parent = avl_tree_swap_with_successor(root_ptr, node,
						      &left_deleted);
		/* @parent is now the parent of what was @node's in-order
		 * successor.  It cannot be NULL, since @node itself was
		 * an ancestor of its in-order successor.
		 * @left_deleted has been set to %true if @node's
		 * in-order successor was the left child of @parent,
		 * otherwise %false.  */
	} else {
		struct avl_tree_node *child;

		/* @node is missing at least one child.  Unlink it.  Set
		 * @parent to @node's parent, and set @left_deleted to
		 * reflect which child of @parent @node was.  Or, if
		 * @node was the root node, simply update the root node
		 * and return.  */
		child = node->left ? node->left : node->right;
		parent = avl_get_parent(node);
		if (parent) {
			if (node == parent->left) {
				parent->left = child;
				left_deleted = true;
			} else {
				parent->right = child;
				left_deleted = false;
			}
			if (child)
				avl_set_parent(child, parent);
		} else {
			if (child)
				avl_set_parent(child, parent);
			*root_ptr = child;
			return;
		}
	}

	/* Rebalance the tree.  */
	do {
		if (left_deleted)
			parent = avl_handle_subtree_shrink(root_ptr, parent,
							   +1, &left_deleted);
		else
			parent = avl_handle_subtree_shrink(root_ptr, parent,
							   -1, &left_deleted);
	} while (parent);
}
Beispiel #3
0
/*
 * Template for performing a single rotation ---
 *
 * sign > 0:  Rotate clockwise (right) rooted at A:
 *
 *           P?            P?
 *           |             |
 *           A             B
 *          / \           / \
 *         B   C?  =>    D?  A
 *        / \               / \
 *       D?  E?            E?  C?
 *
 * (nodes marked with ? may not exist)
 *
 * sign < 0:  Rotate counterclockwise (left) rooted at A:
 *
 *           P?            P?
 *           |             |
 *           A             B
 *          / \           / \
 *         C?  B   =>    A   D?
 *            / \       / \
 *           E?  D?    C?  E?
 *
 * This updates pointers but not balance factors!
 */
static AVL_INLINE void
avl_rotate(struct avl_tree_node ** const root_ptr,
	   struct avl_tree_node * const A, const int sign)
{
	struct avl_tree_node * const B = avl_get_child(A, -sign);
	struct avl_tree_node * const E = avl_get_child(B, +sign);
	struct avl_tree_node * const P = avl_get_parent(A);

	avl_set_child(A, -sign, E);
	avl_set_parent(A, B);

	avl_set_child(B, +sign, A);
	avl_set_parent(B, P);

	if (E)
		avl_set_parent(E, A);

	avl_replace_child(root_ptr, P, A, B);
}
Beispiel #4
0
INLINE struct avl_node* _rotate_RR(struct avl_node *parent,
                                   int parent_bf,
                                   int *child_bf,
                                   int *height_delta)
// MUST ensure that parent_bf >= 0
{
    int p_left, c_left, c_right;
    struct avl_node *child = parent->right;

    __AVL_DEBUG_RR(parent, child, parent_bf, *child_bf);

    c_left = (child->left)?(1):(0);
    c_right = (child->right)?(1):(0);
    if (*child_bf < 0) {
        // child->left > child->right
        c_left = c_right - (*child_bf);
        p_left = c_left + 1 - parent_bf;
        if (height_delta)
            *height_delta = max(c_right, max(c_left, p_left)+1) - (c_left + 1);

    } else {
        // child->left <= child->right
        c_right = c_left + (*child_bf);
        p_left = c_right + 1 - parent_bf;
        if (height_delta)
            *height_delta = max(c_right, max(c_left, p_left)+1) - (c_right + 1);

    }
    *child_bf = c_right - (max(c_left, p_left) + 1);
    avl_set_bf(parent, c_left - p_left);

    parent->right = child->left;
    if (child->left)
        avl_set_parent(child->left, parent);
    child->left = parent;
    avl_set_parent(child, avl_parent(parent));
    avl_set_parent(parent, child);

    return child;
}
Beispiel #5
0
/* Swaps node X, which must have 2 children, with its in-order successor, then
 * unlinks node X.  Returns the parent of X just before unlinking, without its
 * balance factor having been updated to account for the unlink.  */
static AVL_INLINE struct avl_tree_node *
avl_tree_swap_with_successor(struct avl_tree_node **root_ptr,
			     struct avl_tree_node *X,
			     bool *left_deleted_ret)
{
	struct avl_tree_node *Y, *ret;

	Y = X->right;
	if (!Y->left) {
		/*
		 *     P?           P?           P?
		 *     |            |            |
		 *     X            Y            Y
		 *    / \          / \          / \
		 *   A   Y    =>  A   X    =>  A   B?
		 *      / \          / \
		 *    (0)  B?      (0)  B?
		 *
		 * [ X unlinked, Y returned ]
		 */
		ret = Y;
		*left_deleted_ret = false;
	} else {
		struct avl_tree_node *Q;

		do {
			Q = Y;
			Y = Y->left;
		} while (Y->left);

		/*
		 *     P?           P?           P?
		 *     |            |            |
		 *     X            Y            Y
		 *    / \          / \          / \
		 *   A   ...  =>  A  ...   =>  A  ...
		 *       |            |            |
		 *       Q            Q            Q
		 *      /            /            /
		 *     Y            X            B?
		 *    / \          / \
		 *  (0)  B?      (0)  B?
		 *
		 *
		 * [ X unlinked, Q returned ]
		 */

		Q->left = Y->right;
		if (Q->left)
			avl_set_parent(Q->left, Q);
		Y->right = X->right;
		avl_set_parent(X->right, Y);
		ret = Q;
		*left_deleted_ret = true;
	}

	Y->left = X->left;
	avl_set_parent(X->left, Y);

	Y->parent_balance = X->parent_balance;
	avl_replace_child(root_ptr, avl_get_parent(X), X, Y);

	return ret;
}
Beispiel #6
0
void avl_remove(struct avl_tree *tree,
                struct avl_node *node)
{
    __AVL_DEBUG_REMOVE(node);

    // not found
    if (node == NULL) return;

    struct avl_tree right_subtree;
    struct avl_node *p=NULL,*cur, *next=NULL;
    int bf = 0, bf_old;


#ifdef _AVL_NEXT_POINTER
    if (node->prev) node->prev->next = node->next;
    if (node->next) node->next->prev = node->prev;
#endif

    // find smallest node in right sub-tree
    right_subtree.root = node->right;
    next = avl_first(&right_subtree);

    if (next) {
        // 1. NEXT exists
        if (avl_parent(next)) {
            if (avl_parent(next) != node) {
                // NODE is not NEXT's direct parent
                // MUST ensure NEXT should be *left child* of its parent
                // MUST ensure NEXT doesn't have right child
                avl_parent(next)->left = next->right;
                if (next->right)
                    avl_set_parent(next->right, avl_parent(next));
            }
        }
        if (avl_parent(node)) {
            // replace NODE by NEXT
            if (avl_parent(node)->left == node) {
                avl_parent(node)->left = next;
            } else {
                avl_parent(node)->right = next;
            }
        }

        // re-link pointers
        if (node->right != next) {
            next->right = node->right;
            if (node->right) avl_set_parent(node->right, next);
            cur = avl_parent(next);
            bf = 1;
        }else{
            cur = next;
            bf = -1;
        }

        next->left = node->left;
        if (node->left) avl_set_parent(node->left, next);
        avl_set_parent(next, avl_parent(node));

        // inherit NODE's balance factor
        avl_set_bf(next, avl_bf(node));

    } else {
        // 2. NEXT == NULL (only when there's no right sub-tree)
        p = avl_parent(node);
        if (p) {
            if (p->left == node) {
                p->left = node->left;
                bf = 1;
            } else {
                p->right = node->left;
                bf = -1;
            }
        }
        if (node->left)
            avl_set_parent(node->left, p);

        cur = avl_parent(node);
    }

    // reset root
    if (tree->root == node) {
        tree->root = next;
        if (next == NULL) {
            if (node->left) tree->root = node->left;
        }
    }

    // recursive balancing process .. scan from CUR to root
    while(cur) {
        p = avl_parent(cur);
        if (p) {
            // if parent exists
            bf_old = avl_bf(cur);

            if (p->right == cur) {
                cur = _balance_tree(cur, bf);
                p->right = cur;
            }else {
                cur = _balance_tree(cur, bf);
                p->left = cur;
            }

            // calculate balance facter BF for parent
            if (cur->left == NULL && cur->right == NULL) {
                // leaf node
                if (p->left == cur) bf = 1;
                else bf = -1;
            } else {
                // index ndoe
                bf = 0;
                if (_abs(bf_old) > _abs(avl_bf(cur))) {
                    // if ABS of balance factor decreases
                    // cascade to parent
                    if (p->left == cur) bf = 1;
                    else bf = -1;
                }
            }

        } else if(cur == tree->root){
            tree->root = _balance_tree(tree->root, bf);
            break;
        }
        if (bf == 0) break;

        cur = p;
    }

    __AVL_DEBUG_DISPLAY(tree);
}
Beispiel #7
0
struct avl_node* avl_insert(struct avl_tree *tree,
                            struct avl_node *node,
                            avl_cmp_func *func)
{
    __AVL_DEBUG_INSERT(node);

    struct avl_node *p=NULL,*cur;
    int cmp, bf, bf_old;

    cur = tree->root;
    while(cur)
    {
        cmp = func(cur, node, tree->aux);
        p = cur;

        if(cmp > 0) {
            cur = cur->left;
        }else if (cmp < 0){
            cur = cur->right;
        }else {
            // duplicated key -> return
            return cur;
        }
    }

    avl_set_parent(node, p);
    avl_set_bf(node, 0);
    node->left = node->right = NULL;
#ifdef _AVL_NEXT_POINTER
    node->prev = node->next = NULL;
#endif

    // P is parent node of CUR
    if(p) {
        if(func(p, node, tree->aux) > 0) {
            p->left = node;
#ifdef _AVL_NEXT_POINTER
            node->next = p;
            node->prev = p->prev;
            if (p->prev) p->prev->next = node;
            p->prev = node;
#endif

        }else {
            p->right = node;
#ifdef _AVL_NEXT_POINTER
            node->prev = p;
            node->next = p->next;
            if (p->next) p->next->prev = node;
            p->next = node;
#endif
        }

    } else {
        // no parent .. make NODE as root
        tree->root = node;
    }

    // recursive balancing process .. scan from leaf to root
    bf = 0;
    while(node) {
        p = avl_parent(node);

        if (p) {
            // if parent exists
            bf_old = avl_bf(node);

            if (p->right == node) {
                node = _balance_tree(node, bf);
                p->right = node;
            }else {
                node = _balance_tree(node, bf);
                p->left = node;
            }

            // calculate balance facter BF for parent
            if (node->left == NULL && node->right == NULL) {
                // leaf node
                if (p->left == node) bf = -1;
                else bf = 1;
            } else {
                // index ndoe
                bf = 0;
                if (_abs(bf_old) < _abs(avl_bf(node))) {
                    // if ABS of balance factor increases
                    // cascade to parent
                    if (p->left == node) bf = -1;
                    else bf = 1;
                }
            }

        } else if(node == tree->root){
            tree->root = _balance_tree(tree->root, bf);
            break;
        }
        if (bf == 0) break;

        node = p;
    }

    __AVL_DEBUG_DISPLAY(tree);

    return node;
}