Example #1
0
static void
post_insert(struct avl_tree *tree, struct avl_node *node)
{
  struct avl_node *parent = node->parent;

  if (parent == NULL)
    return;

  if (node == parent->left) {
    parent->balance--;

    if (parent->balance == 0)
      return;

    if (parent->balance == -1) {
      post_insert(tree, parent);
      return;
    }

    if (node->balance == -1) {
      avl_rotate_right(tree, parent);
      return;
    }

    avl_rotate_left(tree, node);
    avl_rotate_right(tree, node->parent->parent);
    return;
  }

  parent->balance++;

  if (parent->balance == 0)
    return;

  if (parent->balance == 1) {
    post_insert(tree, parent);
    return;
  }

  if (node->balance == 1) {
    avl_rotate_left(tree, parent);
    return;
  }

  avl_rotate_right(tree, node);
  avl_rotate_left(tree, node->parent->parent);
}
Example #2
0
/**
 * // node, current node to balance
 * // root, the root node of the tree
 * 
 * RETURNS the new child for the parent
 */
static void avl_balance_node(struct avl_node **parent) 
{
    assert(parent != NULL);
    struct avl_node *node = *parent;

    // get balance for node
    short lh = (node->left != NULL) ? node->left->height : 0;
    short rh = (node->right != NULL) ? node->right->height : 0;
    short balance = lh - rh;

    //printf("balance %d\n", balance);
    if (balance == -1) 
    {
        // handle right subtree too high
        assert(node->right != NULL);
        if((node->right->right != NULL) && 
                (node->right->left != NULL) && 
                LEFT_HEAVY(node->right)) 
        {
            avl_rotate_right(&(node->right));
        }
        avl_rotate_left(parent);
        //printf("rotation done\n");
    } 
    else if (balance == 1) 
    {
        // handle left subtree too high
        // check for left right case
        assert(node->left != NULL);
        if((node->left->left != NULL) && 
                (node->left->right != NULL) && 
                RIGHT_HEAVY(node->left)) 
        {
            avl_rotate_left(&(node->left));
        }
        avl_rotate_right(parent);
        //printf("rotation done\n");
    } 
    else {
        ;
    }
    assert(parent != NULL);
    assert(*parent != NULL);
}
Example #3
0
/* ----
 * avl_insertinto() -
 *
 *	The heart of avl_insert().
 * ----
 */
static int
avl_insertinto(AVLtree *tree, AVLnode **node,
			   void *cdata, AVLnode **result)
{
	int			cmp;

	/*
	 * Compare the node at hand with the new elements key.
	 */
	cmp = (tree->compfunc) (cdata, (*node)->cdata);

	if (cmp > 0)
	{
		/*
		 * New element is > than node. Insert to the right.
		 */
		if ((*node)->rnode == NULL)
		{
			/*
			 * Right side of current node is empty. Create a new node there
			 * and return new maximum depth. Note that this can only be 1
			 * because otherwise this node would have been unbalanced before.
			 */
			(*node)->rnode = *result = avl_makenode();
			(*node)->rdepth = 1;
			return 1;
		}

		/*
		 * Right hand node exists. Recurse into that and remember the new
		 * right hand side depth.
		 */
		(*node)->rdepth = avl_insertinto(tree, &((*node)->rnode),
										 cdata, result) + 1;

		/*
		 * A right hand side insert can unbalance this node only to the right.
		 */
		if (AVL_BALANCE(*node) > 1)
		{
			if (AVL_BALANCE((*node)->rnode) > 0)
			{
				/*
				 * RR situation, rebalance the tree by left rotating this
				 * node.
				 */
				avl_rotate_left(node);
			}
			else
			{
				/*
				 * RL situation, rebalance the tree by first right rotating
				 * the right hand side, then left rotating this node.
				 */
				avl_rotate_right(&((*node)->rnode));
				avl_rotate_left(node);
			}
		}

		return AVL_MAXDEPTH(*node);
	}
	else if (cmp < 0)
	{
		/*
		 * New element is < than node. Insert to the left.
		 */
		if ((*node)->lnode == NULL)
		{
			/*
			 * Left side of current node is empty. Create a new node there and
			 * return new maximum depth. Note that this can only be 1 because
			 * otherwise this node would have been unbalanced before.
			 */
			(*node)->lnode = *result = avl_makenode();
			(*node)->ldepth = 1;
			return AVL_MAXDEPTH(*node);
		}

		/*
		 * Left hand node exists. Recurse into that and remember the new left
		 * hand side depth.
		 */
		(*node)->ldepth = avl_insertinto(tree, &((*node)->lnode),
										 cdata, result) + 1;

		/*
		 * A left hand side insert can unbalance this node only to the left.
		 */
		if (AVL_BALANCE(*node) < -1)
		{
			if (AVL_BALANCE((*node)->lnode) < 0)
			{
				/*
				 * LL situation, rebalance the tree by right rotating this
				 * node.
				 */
				avl_rotate_right(node);
			}
			else
			{
				/*
				 * LR situation, rebalance the tree by first left rotating the
				 * left node, then right rotating this node.
				 */
				avl_rotate_left(&((*node)->lnode));
				avl_rotate_right(node);
			}
		}

		return AVL_MAXDEPTH(*node);
	}
	else
	{
		/*
		 * The new element is equal to this node. If it is marked for
		 * deletion, free the user element data now. The caller is supposed to
		 * replace it with a new element having the the key.
		 */
		if ((*node)->deleted && tree->freefunc != NULL)
		{
			(tree->freefunc) ((*node)->cdata);
			(*node)->cdata = NULL;
			(*node)->deleted = 0;
		}
		*result = *node;
		return AVL_MAXDEPTH(*node);
	}
}