Example #1
0
/* The tree is overbalanced to the right, so we rotate nodes to the left */
static int tree_node_rotate_left(Edata_Tree *tree, Edata_Tree_Node *top_node)
{
	Edata_Tree_Node *temp;

	CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE);

	/*
	 * The right branch's left branch becomes the nodes right branch,
	 * the right branch becomes the top node, and the node becomes the
	 * left branch.
	 */
	temp = top_node->left_child;
	top_node->left_child = temp->right_child;
	temp->right_child = top_node;

	/* Make sure the nodes know who their new parents are. */
	temp->parent = top_node->parent;
	if (temp->parent == NULL)
		tree->tree = temp;
	else
	{
		if (temp->parent->left_child == top_node)
			temp->parent->left_child = temp;
		else
			temp->parent->right_child = temp;
	}
	top_node->parent = temp;

	/* And recalculate node heights */
	tree_node_balance(tree, top_node);
	tree_node_balance(tree, temp);

	return TRUE;
}
Example #2
0
/**
 * Set the value associated with key to @a value.
 * @param  tree  The tree that contains the key/value pair.
 * @param  key   The key to identify which node to set a value.
 * @param  value Value to set the found node.
 * @return TRUE if successful, FALSE if not.
 */
EAPI int edata_tree_set(Edata_Tree *tree, void *key, void *value)
{
	Edata_Tree_Node *node = NULL;

	CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);

	node = tree_node_find(tree, key);
	if (!node)
	{
		node = edata_tree_node_new();
		edata_tree_node_key_set(node, key);
		if (!edata_tree_node_add(tree, node))
			return FALSE;
	}
	else
	{
		if (tree->free_key)
			tree->free_key(key);
		if (node->value && tree->free_value)
			tree->free_value(node->value);
	}

	edata_tree_node_value_set(node, value);

	for (; node; node = node->parent)
		tree_node_balance(tree, node);

	return TRUE;
}
Example #3
0
static DirectNode *
tree_node_insert (DirectTree *tree,
                  DirectNode *node,
                  void       *key,
                  void       *value,
                  int        *inserted)
{
     int cmp;
     int old_balance;

     if (!node) {
          *inserted = 1;
          return tree_node_new (tree, key, value);
     }

     cmp = key - node->key;
     if (cmp == 0) {
          node->value = value;
          return node;
     }

     if (cmp < 0) {
          if (node->left) {
               old_balance = node->left->balance;
           node->left = tree_node_insert (tree, node->left,
                                              key, value, inserted);

               if ((old_balance != node->left->balance) && node->left->balance)
                   node->balance -= 1;
          }
          else {
               *inserted = 1;
               node->left = tree_node_new (tree, key, value);
               node->balance -= 1;
          }
     }
     else if (cmp > 0) {
          if (node->right) {
               old_balance = node->right->balance;
               node->right = tree_node_insert (tree, node->right,
                                               key, value, inserted);

               if ((old_balance != node->right->balance) && node->right->balance)
                    node->balance += 1;
          }
          else {
               *inserted = 1;
               node->right = tree_node_new (tree, key, value);
               node->balance += 1;
          }
     }

     if (*inserted && (node->balance < -1 || node->balance > 1))
          node = tree_node_balance (node);

     return node;
}
Example #4
0
/**
 * Remove the node from the tree.
 * @param  tree The tree to remove @a node from.
 * @param  node The node to remove from @a tree.
 * @return TRUE on a successful remove, FALSE otherwise.
 */
EAPI int edata_tree_node_remove(Edata_Tree *tree, Edata_Tree_Node *node)
{
	Edata_Tree_Node *traverse;

	CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
	CHECK_PARAM_POINTER_RETURN("node", node, FALSE);

	/*
	 * Find the nearest value to the balanced one.
	 */
	if (node->left_child)
	{
		traverse = node->left_child;

		/* Now work our way down right side of the traverse node.
		 * This will give us the node with the next closest value
		 * to the current node. If traverse had no right node, then
		 * this will stop at node's left node. */
		while (traverse->right_child)
		{
			traverse = traverse->right_child;
		}

		/*
		 * Hook any dropped leaves into the moved nodes spot
		 */
		if (traverse->parent)
			traverse->parent->left_child = traverse->left_child;
	}
	else if (node->right_child)
	{
		traverse = node->right_child;

		/* Now work our way down left side of the traverse node.
		 * This will give us the node with the next closest value
		 * to the current node. If traverse had no left node, then
		 * this will stop at node's right node. */
		while (traverse->left_child)
		{
			traverse = traverse->left_child;
		}

		/*
		 * Hook any dropped leaves into the moved nodes spot
		 */
		if (traverse->right_child)
			traverse->right_child->parent = traverse->parent;

		if (traverse->parent)
			traverse->parent->right_child = traverse->right_child;
		else
			tree->tree = traverse->right_child;
	}
	else
		traverse = NULL;

	if (traverse)
	{

		/*
		 * Ensure that we don't get a recursive reference.
		 */
		if (node->right_child && node->right_child != traverse)
		{
			node->right_child->parent = traverse;
			traverse->right_child = node->right_child;
		}

		if (node->left_child && node->left_child != traverse)
		{
			node->left_child->parent = traverse;
			traverse->left_child = node->left_child;
		}

		/*
		 * Unlink the node to be moved from it's parent.
		 */
		if (traverse->parent)
		{
			if (traverse->parent->left_child == traverse)
				traverse->parent->left_child = NULL;
			else
				traverse->parent->right_child = NULL;
		}
		traverse->parent = node->parent;
	}

	if (node->parent)
	{
		if (node == node->parent->left_child)
			node->parent->left_child = traverse;
		else
			node->parent->right_child = traverse;
	}

	if (tree->tree == node)
		tree->tree = traverse;

	node->parent = node->left_child = node->right_child = NULL;

	/*
	 * Rebalance the tree to ensure short search paths.
	 */
	while (traverse)
	{
		tree_node_balance(tree, traverse);
		traverse = traverse->parent;
	}

	return TRUE;
}