Beispiel #1
0
/* This is a copy-cat of the previous loop,
 * with the exception that the heuristic to break
 * the loop is different.
 */
static inline void
avl_rebalance_after_delete(struct rope_node ***path,
			   struct rope_node ***p_end)
{
	while (p_end > path) {
		struct rope_node *left = **p_end--;
		struct rope_node *parent = **p_end;

		int mirror = left != parent->link[0];

		struct rope_node *right = parent->link[!mirror];

		int left_height = rope_node_height(left);
		int right_height = rope_node_height(right);

		parent->height = MAX(left_height, right_height) + 1;
		/*
		 * Right was taller, and we deleted from the left.
		 * We can break the loop since there can be no
		 * changes in height up in the route.
		 */
		if (left_height - right_height == -1)
			break;

		if (left_height - right_height <= -2) {
			struct rope_node *r_left = right->link[mirror];
			struct rope_node *r_right = right->link[!mirror];
			int r_left_height = rope_node_height(r_left);
			int r_right_height = rope_node_height(r_right);

			if (r_left_height <= r_right_height)
				**p_end = avl_rotate_single(parent, mirror);
			else
				**p_end = avl_rotate_double(parent, mirror);
		}
	}
}
Beispiel #2
0
Datei: avl.c Projekt: axn/bmxd
void *avl_remove(struct avl_tree *tree, void *key)
{
        struct avl_node *it = tree->root;
        struct avl_node *up[AVL_MAX_HEIGHT];
        int upd[AVL_MAX_HEIGHT], top = 0, cmp;

        paranoia(-500182, !it); // paranoia if not found

//        while ((cmp = memcmp(it->key, key, tree->key_size)) ) {
        while ((cmp = memcmp(it->key, key, tree->key_size)) || (it->link[0] && !memcmp(it->link[0]->key, key, tree->key_size))) {

                // Push direction and node onto stack
                upd[top] = (cmp < 0);
                up[top] = it;
                top++;

                if (!(it = it->link[(cmp < 0)]))
                        return NULL;

        }

        // remember and return the found key. It might have been another one than intended
        key = it->key;

        // Remove the node:
        if (!(it->link[0] && it->link[1])) { // at least one child is NULL:

                // Which child is not null?
                int dir = !(it->link[0]);

                /* Fix parent */
                if (top) {
                        up[top - 1]->link[upd[top - 1]] = it->link[dir];
                        if (it->link[dir])
                                it->link[dir]->up = up[top - 1];
                } else {
                        tree->root = it->link[dir];
                        if (tree->root)
                                tree->root->up = NULL;
                }
                debugFree(it, 1327);

        } else { // both childs NOT NULL:

                // Find the inorder successor
                struct avl_node *heir = it->link[1];

                // Save the path
                upd[top] = 1;
                up[top] = it;
                top++;

                while (heir->link[0]) {
                        upd[top] = 0;
                        up[top] = heir;
                        top++;
                        heir = heir->link[0];
                }

                // Swap data
                it->key = heir->key;

                // Unlink successor and fix parent
                up[top - 1]->link[ (up[top - 1] == it) ] = heir->link[1];

                if ( heir->link[1])
                        heir->link[1]->up = up[top - 1];

                debugFree(heir, 2327);
        }

        // Walk back up the search path
        while (--top >= 0) {
                int lh = avl_height(up[top]->link[upd[top]]);
                int rh = avl_height(up[top]->link[!upd[top]]);
                int max = avl_max(lh, rh);

                /* Update balance factors */
                up[top]->balance = max + 1;


                // Terminate or re-balance as necessary:
                if (lh - rh >= 0)  // re-balance upper path...
                        continue;

                if (lh - rh == -1) // balance for upper path unchanged!
                        break;

                if (!(up[top]) || !(up[top]->link[!upd[top]])) {
                        dbgf(DBGL_SYS, DBGT_ERR, "up(top) %p  link %p   lh %d   rh %d",
                                (void*)(up[top]), (void*)((up[top]) ? (up[top]->link[!upd[top]]) : NULL), lh, rh);

                        paranoia(-500187, (!(up[top])));
                        paranoia(-500188, (!(up[top]->link[!upd[top]])));
                }
/*
                paranoia(-500183, (lh - rh <= -3) );
                paranoia(-500185, (lh - rh == 2) );
                paranoia(-500186, (lh - rh >= 3) );
*/

                // if (lh - rh <= -2):  rebalance here and upper path

                struct avl_node *a = up[top]->link[!upd[top]]->link[upd[top]];
                struct avl_node *b = up[top]->link[!upd[top]]->link[!upd[top]];

                if (avl_height(a) <= avl_height(b))
                        up[top] = avl_rotate_single(up[top], upd[top]);
                else
                        up[top] = avl_rotate_double(up[top], upd[top]);

                // Fix parent:
                if (top) {
                        up[top - 1]->link[upd[top - 1]] = up[top];
                        up[top]->up = up[top - 1];
                } else {
                        tree->root = up[0];
                        tree->root->up = NULL;
                }
        }

        return key;

}
Beispiel #3
0
/** Rebalance the tree. */
static inline void
avl_rebalance_after_insert(struct rope_node ***path,
			   struct rope_node ***p_end, int insert_height)
{
	while (p_end > path) {
		struct rope_node *left = **p_end--;
		struct rope_node *parent = **p_end;
		/*
		 * To use the same rotation functions, set mirror
		 * to 1 if left is right and right is left.
		 */
		int mirror = left != parent->link[0];
		struct rope_node *right = parent->link[!mirror];

		int left_height = rope_node_height(left);
		int right_height = rope_node_height(right);
		parent->height = MAX(left_height, right_height) + 1;
		/*
		 * Rotations flattened the tree, so there is no
		 * further changes in height up the insertion
		 * path.
		 */
		if (left_height == right_height)
			break;
		/*
		 * We've been adding a new child (children) to the
		 * 'left' subtree, so it couldn't get shorter.
		 * The old difference between subtrees was in the
		 * range -1..1. So the new difference can only be
		 * in the range -1..1 + height(new_node).
		 */
		if (left_height - right_height >= 2) {
			struct rope_node *l_left = left->link[mirror];
			struct rope_node *l_right = left->link[!mirror];
			int l_left_height = rope_node_height(l_left);
			int l_right_height = rope_node_height(l_right);
			/*
			 * Rotate in the direction, opposite to
			 * the skew. E.g. if we have two left-left
			 * nodes hanging off the tree, rotate the
			 * parent clockwise. If we have a left
			 * node with a right child, rotate the
			 * child counterclockwise, and then the whole
			 * thing clockwise.
			 */
			if (l_left_height >= l_right_height)
				**p_end = avl_rotate_single(parent,
							    !mirror);
			else
				**p_end = avl_rotate_double(parent,
							    !mirror);
			/*
			 * If we inserted only one node, no more
			 * than 1 rotation is required (see
			 * D. Knuth, Introduction to Algorithms,
			 * vol. 3.). For 2 nodes, its max
			 * 2 rotations.
			 */
			if (l_left_height != l_right_height &&
			    --insert_height == 0)
				break;
		}
	}
}
Beispiel #4
0
Datei: avl.c Projekt: axn/bmxd
void avl_insert(struct avl_tree *tree, void *key) {

        if (tree->root) {

                struct avl_node *it = tree->root;
                struct avl_node *up[AVL_MAX_HEIGHT];
                int upd[AVL_MAX_HEIGHT], top = 0;
                int done = 0;

                /* Search for an empty link, save the path */
                for (;;) {
                        /* Push direction and node onto stack */
//                        upd[top] = memcmp(it->key, key, tree->key_size) < 0;
                        upd[top] = memcmp(it->key, key, tree->key_size) <= 0;
                        up[top++] = it;

                        if (it->link[upd[top - 1]] == NULL)
                                break;

                        it = it->link[upd[top - 1]];
                }

                /* Insert a new node at the bottom of the tree */
                it->link[upd[top - 1]] = avl_create_node(key);
                it->link[upd[top - 1]]->up = it;

                paranoia(-500178, (it->link[upd[top - 1]] == NULL));

                /* Walk back up the search path */
                while (--top >= 0 && !done) {

                        int lh, rh, max;

                        lh = avl_height(up[top]->link[upd[top]]);
                        rh = avl_height(up[top]->link[!upd[top]]);

                        /* Terminate or rebalance as necessary */
                        if (lh - rh == 0)
                                done = 1;
                        if (lh - rh >= 2) {
                                struct avl_node *a = up[top]->link[upd[top]]->link[upd[top]];
                                struct avl_node *b = up[top]->link[upd[top]]->link[!upd[top]];

                                if (avl_height(a) >= avl_height(b))
                                        up[top] = avl_rotate_single(up[top], !upd[top]);
                                else
                                        up[top] = avl_rotate_double(up[top], !upd[top]);

                                /* Fix parent */
                                if (top != 0) {
                                        up[top - 1]->link[upd[top - 1]] = up[top];
                                        up[top]->up = up[top - 1];
                                } else {
                                        tree->root = up[0];
                                        up[0]->up = NULL;

                                }

                                done = 1;
                        }

                        /* Update balance factors */
                        lh = avl_height(up[top]->link[upd[top]]);
                        rh = avl_height(up[top]->link[!upd[top]]);
                        max = avl_max(lh, rh);

                        up[top]->balance = max + 1;
                }

        } else {

                tree->root = avl_create_node(key);
                paranoia( -500179, (tree->root==NULL));

        }

        return;
}