예제 #1
0
static void verify_tree (c_avl_node_t *n)
{
	if (n == NULL)
		return;

	verify_tree (n->left);
	verify_tree (n->right);

	assert ((BALANCE (n) >= -1) && (BALANCE (n) <= 1));
	assert ((n->parent == NULL) || (n->parent->right == n) || (n->parent->left == n));
} /* void verify_tree */
예제 #2
0
파일: avl.c 프로젝트: Emeraude/AVL
static void balance(t_avl const *const avl, t_node **const root) {
  int b = BALANCE(*root) / 2;

  if (b) {
    int const side = (1 - b) / 2;
    if (BALANCE((*root)->node[side]) == -b)
      rotate(avl, &(*root)->node[side], !side);
    *root = rotate(avl, root, side);
  }
  if (*root != nil)
    (*root)->height = 1 + MAX((*root)->node[0]->height, (*root)->node[1]->height);
}
예제 #3
0
static void rebalance (c_avl_tree_t *t, c_avl_node_t *n)
{
	int b_top;
	int b_bottom;

	while (n != NULL)
	{
		b_top = BALANCE (n);
		assert ((b_top >= -2) && (b_top <= 2));

		if (b_top == -2)
		{
			assert (n->right != NULL);
			b_bottom = BALANCE (n->right);
			assert ((b_bottom >= -1) && (b_bottom <= 1));
			if (b_bottom == 1)
				n = rotate_right_left (t, n);
			else
				n = rotate_left (t, n);
		}
		else if (b_top == 2)
		{
			assert (n->left != NULL);
			b_bottom = BALANCE (n->left);
			assert ((b_bottom >= -1) && (b_bottom <= 1));
			if (b_bottom == -1)
				n = rotate_left_right (t, n);
			else
				n = rotate_right (t, n);
		}
		else
		{
			int height = calc_height (n);
			if (height == n->height)
				break;
			n->height = height;
		}

		assert (n->height == calc_height (n));

		n = n->parent;
	} /* while (n != NULL) */
} /* void rebalance */
예제 #4
0
파일: avl.c 프로젝트: Emeraude/AVL
/* deletion */
static void __remove(t_avl const *const avl, t_node **const root, void *val) {
  if (*root == nil)
    return;
  if (!avl->hook_cmp((*root)->val, val)) {
    if ((*root = rotate(avl, root, BALANCE(*root) < 0)) == nil)
      return;
  }
  __remove(avl, &(*root)->node[avl->hook_cmp(val, (*root)->val) < 0], val);
  balance(avl, root);
}
예제 #5
0
static node_t *
avl_single(node_t *root, int dir)
{
  node_t *save = root->link[!dir];
	int rlh, rrh, slh;

	
	root->link[!dir] = save->link[dir];
	save->link[dir] = root;

	
	rlh = height(root->link[0]);
	rrh = height(root->link[1]);
	slh = height(save->link[!dir]);

	BALANCE(root) = avl_max(rlh, rrh) + 1;
	BALANCE(save) = avl_max(slh, BALANCE(root)) + 1;

	return save;
}
예제 #6
0
LIB_EXPORT rc_t CC BSTreeInsert ( BSTree *bt, BSTNode *n,
    int64_t ( CC * sort ) ( const BSTNode *n, const BSTNode *p ) )
{
    if ( bt != NULL && n != NULL )
    {
        int64_t diff;

        BSTNode *p = bt -> root;
        BSTNode *q = NULL;
        BSTNode *y = NULL;

        while ( p != NULL )
        {
            diff = ( * sort ) ( n, p );
            q = p;
            if ( BALANCE ( p ) != 0 )
                y = p;
            p = p -> child [ diff > 0 ];
        }

        n -> par = q;
        n -> child [ 0 ] = n -> child [ 1 ] = NULL;

        if ( q == NULL )
            bt -> root = n;
        else
        {
            q -> child [ diff > 0 ] = n;

            /* run a trace-back */
            for ( p = n; q != y; )
            {
                /* this is safe because q has 0 balance */
                BSTNode *z = q -> par;
                if ( q -> child [ 0 ] == p )
                    SET_BALANCE ( q, LEFT );
                else
                    SET_BALANCE ( q, RIGHT );

                p = q;
                q = z;
            }

            /* rebalance */
            if ( q != NULL )
                RebalanceAfterInsert ( & bt -> root, q, p );
        }
    }

    /* never fails in this implementation */
    return 0;
}
예제 #7
0
static
void CC RebalanceAfterInsert ( BSTNode **root, BSTNode *y, BSTNode *x )
{
    BSTNode *w, *z;

    /* detect left insertion */
    if ( y -> child [ 0 ] == x )
    {
        /* if y was right-heavy, done */
        if ( RIGHT_HEAVY ( y ) )
        {
            CLR_BALANCE ( y, RIGHT );
            return;
        }

        /* rebalance left insertion */
        w = RebalanceLeft ( y, x );
    }

    /* right insertion */
    else
    {
        /* if y was left-heavy, done */
        if ( LEFT_HEAVY ( y ) )
        {
            CLR_BALANCE ( y, LEFT );
            return;
        }

        /* rebalance right insertion */
        w = RebalanceRight ( y, x );
    }

    /* fix parent to child */
    assert ( BALANCE ( w ) == 0 );
    z = w -> par;
    if ( z == 0 )
        * root = w;
    else
        z -> child [ z -> child [ 1 ] == y ] = w;
}
예제 #8
0
BSTNode* CC RotateRightAtXLeftAtY ( BSTNode *y, BSTNode *x )
{
    BSTNode *w = x -> child [ 0 ];
    BSTNode *z = w -> child [ 1 ];
    x -> child [ 0 ] = z;
    if ( z != 0 )
        SET_PARENT ( z, x );
    z = w -> child [ 0 ];
    w -> child [ 1 ] = x;
    y -> child [ 1 ] = z;
    w -> child [ 0 ] = y;
        
    switch ( BALANCE ( w ) )
    {
    case 0:
        w -> par = PARENT ( y );
        x -> par = w;
        y -> par = w;
        break;
    case LEFT:
        w -> par = PARENT ( y );
        SET_PARBAL ( x, w, RIGHT );
        y -> par = w;
        break;
    case RIGHT:
        w -> par = PARENT ( y );
        x -> par = w;
        SET_PARBAL ( y, w, LEFT );
        break;
    }

    /* patch parent link */
    if ( z != 0 )
        SET_PARENT ( z, y );

    return w;
}
예제 #9
0
static int _remove (c_avl_tree_t *t, c_avl_node_t *n)
{
	assert ((t != NULL) && (n != NULL));

	if ((n->left != NULL) && (n->right != NULL))
	{
		c_avl_node_t *r; /* replacement node */
		if (BALANCE (n) > 0) /* left subtree is higher */
		{
			assert (n->left != NULL);
			r = c_avl_node_prev (n);
			
		}
		else /* right subtree is higher */
		{
			assert (n->right != NULL);
			r = c_avl_node_next (n);
		}

		assert ((r->left == NULL) || (r->right == NULL));

		/* copy content */
		n->key   = r->key;
		n->value = r->value;

		n = r;
	}

	assert ((n->left == NULL) || (n->right == NULL));

	if ((n->left == NULL) && (n->right == NULL))
	{
		/* Deleting a leave is easy */
		if (n->parent == NULL)
		{
			assert (t->root == n);
			t->root = NULL;
		}
		else
		{
			assert ((n->parent->left == n)
					|| (n->parent->right == n));
			if (n->parent->left == n)
				n->parent->left = NULL;
			else
				n->parent->right = NULL;

			rebalance (t, n->parent);
		}

		free_node (n);
	}
	else if (n->left == NULL)
	{
		assert (BALANCE (n) == -1);
		assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
		if (n->parent == NULL)
		{
			assert (t->root == n);
			t->root = n->right;
		}
		else if (n->parent->left == n)
		{
			n->parent->left = n->right;
		}
		else
		{
			n->parent->right = n->right;
		}
		n->right->parent = n->parent;

		if (n->parent != NULL)
			rebalance (t, n->parent);

		n->right = NULL;
		free_node (n);
	}
	else if (n->right == NULL)
	{
		assert (BALANCE (n) == 1);
		assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
		if (n->parent == NULL)
		{
			assert (t->root == n);
			t->root = n->left;
		}
		else if (n->parent->left == n)
		{
			n->parent->left = n->left;
		}
		else
		{
			n->parent->right = n->left;
		}
		n->left->parent = n->parent;

		if (n->parent != NULL)
			rebalance (t, n->parent);

		n->left = NULL;
		free_node (n);
	}
	else
	{
		assert (0);
	}

	return (0);
} /* void *_remove */
예제 #10
0
extern int
avl_remove(node_t **rootaddr, PyObject *key)
{
	node_t *root = *rootaddr;
	int cmp_res;

	if (root != NULL) {
		node_t *it, *up[32];
		int upd[32], top = 0;

		it = root;
		for (;;) {
			
			if (it == NULL)
				return 0;
			cmp_res = ct_compare(KEY(it), key);
			if (cmp_res == 0)
				break;

			
			upd[top] = (cmp_res < 0);
			up[top++] = it;
			it = it->link[upd[top - 1]];
		}

		
		if (it->link[0] == NULL ||
			it->link[1] == NULL) {
			
			int dir = it->link[0] == NULL;

			
			if (top != 0)
				up[top - 1]->link[upd[top - 1]] = it->link[dir];
			else
				root = it->link[dir];

			ct_delete_node(it);
		}
		else {
			
			node_t *heir = it->link[1];

			
			upd[top] = 1;
			up[top++] = it;

			while ( heir->link[0] != NULL ) {
				upd[top] = 0;
				up[top++] = heir;
				heir = heir->link[0];
			}
			
			ct_swap_data(it, heir);
			
			up[top - 1]->link[up[top - 1] == it] = heir->link[1];
			ct_delete_node(heir);
		}

		
		while (--top >= 0) {
			int lh = height(up[top]->link[upd[top]]);
			int rh = height(up[top]->link[!upd[top]]);
			int max = avl_max(lh, rh);

			
			BALANCE(up[top]) = max + 1;

			
			if (lh - rh == -1)
				break;
			if (lh - rh <= -2) {
				node_t *a = up[top]->link[!upd[top]]->link[upd[top]];
				node_t *b = up[top]->link[!upd[top]]->link[!upd[top]];

				if (height(a) <= height(b))
					up[top] = avl_single(up[top], upd[top]);
				else
					up[top] = avl_double(up[top], upd[top]);

				
				if (top != 0)
					up[top - 1]->link[upd[top - 1]] = up[top];
				else
					root = up[0];
			}
		}
	}
	(*rootaddr) = root;
	return 1;
}
예제 #11
0
extern int
avl_insert(node_t **rootaddr, PyObject *key, PyObject *value)
{
	node_t *root = *rootaddr;

	if (root == NULL) {
		root = avl_new_node(key, value);
		if (root == NULL)
			return -1; 
	}
	else {
		node_t *it, *up[32];
		int upd[32], top = 0;
		int done = 0;
		int cmp_res;

		it = root;
		
		for (;;) {
			
			cmp_res = ct_compare(KEY(it), key);
			if (cmp_res == 0) {
				Py_XDECREF(VALUE(it)); 
				VALUE(it) = value; 
				Py_INCREF(value); 
				return 0;
			}
			
			upd[top] = (cmp_res < 0);
			up[top++] = it;

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

		
		it->link[upd[top - 1]] = avl_new_node(key, value);
		if (it->link[upd[top - 1]] == NULL)
			return -1; 

		
		while (--top >= 0 && !done) {
			
			int lh, rh, max;

			cmp_res = ct_compare(KEY(up[top]), key);

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

			
			if (lh - rh == 0)
				done = 1;
			if (lh - rh >= 2) {
				node_t *a = up[top]->link[upd[top]]->link[upd[top]];
				node_t *b = up[top]->link[upd[top]]->link[!upd[top]];

				if (height( a ) >= height( b ))
					up[top] = avl_single(up[top], !upd[top]);
				else
					up[top] = avl_double(up[top], !upd[top]);

				
				if (top != 0)
					up[top - 1]->link[upd[top - 1]] = up[top];
				else
					root = up[0];
				done = 1;
			}
			
			lh = height(up[top]->link[upd[top]]);
			rh = height(up[top]->link[!upd[top]]);
			max = avl_max(lh, rh);
			BALANCE(up[top]) = max + 1;
		}
	}
	(*rootaddr) = root;
	return 1;
}
예제 #12
0
/* BSTreeUnlink
 *  removes a node from tree
 */
static
void CC RebalanceAfterUnlink ( BSTNode **root, BSTNode *q, int dir )
{
    while ( q != 0 )
    {
        BSTNode *w, *x, *y = q;
        q = PARENT ( q );

        if ( ! dir )
        {
            if ( q && q -> child [ 1 ] == y )
                dir = 1;

            /* simulate an increment of balance */
            switch ( BALANCE ( y ) )
            {
            case 0:
                SET_BALANCE ( y, RIGHT );
                return;
            case LEFT:
                CLR_BALANCE ( y, LEFT );
                break;
            case RIGHT:
                /* y has just become ++ */
                x = y -> child [ 1 ];
                if ( LEFT_HEAVY ( x ) )
                {
                    w = RotateRightAtXLeftAtY ( y, x );
                    if ( q == 0 )
                        * root = w;
                    else
                        q -> child [ dir ] = w;
                }
                else
                {
                    w = y -> child [ 1 ] = x -> child [ 0 ];
                    x -> child [ 0 ] = y;
                    SET_PARENT ( x, q );
                    SET_PARENT ( y, x );
                    if ( w != 0 )
                        SET_PARENT ( w, y );
                    if ( q == 0 )
                        * root = x;
                    else
                        q -> child [ dir ] = x;
                    if ( BALANCE ( x ) == 0 )
                    {
                        SET_BALANCE ( x, LEFT );
                        SET_PARBAL ( y, x, RIGHT );
                        return;
                    }
                    ZERO_BALANCE ( x );
                    ZERO_BALANCE ( y );
                    /* y = x; */
                }
                break;
            }
        }

        /* symmetric case */
        else
        {
            if ( q && q -> child [ 0 ] == y )
                dir = 0;

            switch ( BALANCE ( y ) )
            {
            case 0:
                SET_BALANCE ( y, LEFT );
                return;
            case LEFT:
                /* y has just become -- */
                x = y -> child [ 0 ];
                if ( RIGHT_HEAVY ( x ) )
                {
                    w = RotateLeftAtXRightAtY ( y, x );
                    if ( q == 0 )
                        * root = w;
                    else
                        q -> child [ dir ] = w;
                }
                else
                {
                    w = x -> child [ 1 ];
                    y -> child [ 0 ] = w;
                    x -> child [ 1 ] = y;
                    SET_PARENT ( x, q );
                    SET_PARENT ( y, x );
                    if ( w != 0 )
                        SET_PARENT ( w, y );
                    if ( q == 0 )
                        * root = x;
                    else
                        q -> child [ dir ] = x;
                    if ( BALANCE ( x ) == 0 )
                    {
                        SET_BALANCE ( x, RIGHT );
                        SET_PARBAL ( y, x, LEFT );
                        return;
                    }
                    ZERO_BALANCE ( x );
                    ZERO_BALANCE ( y );
                    /* y = x; */
                }
                break;
            case RIGHT:
                CLR_BALANCE ( y, RIGHT );
                break;
            }
        }
    }
}
예제 #13
0
/* BSTreeInsertUnique
 *  insert an object within tree, but only if unique
 *  "sort" function returns equivalent of "item" - "n"
 *  returns non-NULL "n" upon match or NULL on success
 */
LIB_EXPORT rc_t CC BSTreeInsertUnique ( BSTree *bt, BSTNode *n, BSTNode **exist,
    int64_t ( CC * sort ) ( const BSTNode *n, const BSTNode *p ) )
{
    if ( bt != NULL && n != NULL )
    {
        int64_t diff;

        BSTNode *p = bt -> root;
        BSTNode *q = NULL;
        BSTNode *y = NULL;

        while ( p != NULL )
        {
            diff = ( * sort ) ( n, p );

            if ( diff == 0 )
            {
                /* fail to insert */
                if ( exist != NULL )
                    * exist = p;
                return RC ( rcCont, rcTree, rcInserting, rcNode, rcExists );
            }

            q = p;
            if ( BALANCE ( p ) != 0 )
                y = p;
            p = p -> child [ diff > 0 ];
        }

        n -> par = q;
        n -> child [ 0 ] = n -> child [ 1 ] = NULL;

        if ( q == NULL )
            bt -> root = n;
        else
        {
            q -> child [ diff > 0 ] = n;

            /* run a trace-back */
            for ( p = n; q != y; )
            {
                /* this is safe because q has 0 balance */
                BSTNode *z = q -> par;
                if ( q -> child [ 0 ] == p )
                    SET_BALANCE ( q, LEFT );
                else
                    SET_BALANCE ( q, RIGHT );

                p = q;
                q = z;
            }

            /* rebalance */
            if ( q != NULL )
                RebalanceAfterInsert ( & bt -> root, q, p );
        }
    }

    /* only fails on existing item in this implementation */
    return 0;
}