Beispiel #1
0
/*
 * Search for the node which contains "value".  The algorithm is a
 * simple binary tree search.
 *
 * return value:
 *	NULL: the value is not in the AVL tree
 *		*where (if not NULL)  is set to indicate the insertion point
 *	"void *"  of the found tree node
 */
void *
avl_find(avl_tree_t *tree, void *value, avl_index_t *where)
{
	avl_node_t *node;
	avl_node_t *prev = NULL;
	int child = 0;
	int diff;
	size_t off = tree->avl_offset;

	for (node = tree->avl_root; node != NULL;
	    node = node->avl_child[child]) {

		prev = node;

		diff = tree->avl_compar(value, AVL_NODE2DATA(node, off));
		if (!((-1 <= diff) && (diff <= 1))) {
			filebench_log(LOG_ERROR, "avl compare error");
			return (NULL);
		}
		if (diff == 0) {
			if (where != NULL)
				*where = 0;

			return (AVL_NODE2DATA(node, off));
		}
		child = avl_balance2child[1 + diff];

	}

	if (where != NULL)
		*where = AVL_MKINDEX(prev, child);

	return (NULL);
}
Beispiel #2
0
/*
 * Search for the node which contains "value".  The algorithm is a
 * simple binary tree search.
 *
 * return value:
 *	NULL: the value is not in the AVL tree
 *		*where (if not NULL)  is set to indicate the insertion point
 *	"void *"  of the found tree node
 */
void *
avl_find(avl_tree_t *tree, const void *value, avl_index_t *where)
{
	avl_node_t *node;
	avl_node_t *prev = NULL;
	int child = 0;
	int diff;
	size_t off = tree->avl_offset;

	for (node = tree->avl_root; node != NULL;
	    node = node->avl_child[child]) {

		prev = node;

		diff = tree->avl_compar(value, AVL_NODE2DATA(node, off));
		//ASSERT(-1 <= diff && diff <= 1);
		if (diff == 0) {
#ifdef DEBUG
			if (where != NULL)
				*where = 0;
#endif
			return (AVL_NODE2DATA(node, off));
		}
		child = avl_balance2child[1 + diff];

	}

	if (where != NULL)
		*where = AVL_MKINDEX(prev, child);

	return (NULL);
}
Beispiel #3
0
/*
 * Insert "new_data" in "tree" in the given "direction" either after or
 * before (AVL_AFTER, AVL_BEFORE) the data "here".
 *
 * Insertions can only be done at empty leaf points in the tree, therefore
 * if the given child of the node is already present we move to either
 * the AVL_PREV or AVL_NEXT and reverse the insertion direction. Since
 * every other node in the tree is a leaf, this always works.
 *
 * To help developers using this interface, we assert that the new node
 * is correctly ordered at every step of the way in DEBUG kernels.
 */
void
avl_insert_here(
	avl_tree_t *tree,
	void *new_data,
	void *here,
	int direction)
{
	avl_node_t *node;
	int child = direction;	/* rely on AVL_BEFORE == 0, AVL_AFTER == 1 */
#ifdef DEBUG
	int diff;
#endif

	//ASSERT(tree != NULL);
	//ASSERT(new_data != NULL);
	//ASSERT(here != NULL);
	//ASSERT(direction == AVL_BEFORE || direction == AVL_AFTER);

	/*
	 * If corresponding child of node is not NULL, go to the neighboring
	 * node and reverse the insertion direction.
	 */
	node = AVL_DATA2NODE(here, tree->avl_offset);

#ifdef DEBUG
	diff = tree->avl_compar(new_data, here);
	//ASSERT(-1 <= diff && diff <= 1);
	//ASSERT(diff != 0);
	//ASSERT(diff > 0 ? child == 1 : child == 0);
#endif

	if (node->avl_child[child] != NULL) {
		node = node->avl_child[child];
		child = 1 - child;
		while (node->avl_child[child] != NULL) {
#ifdef DEBUG
			diff = tree->avl_compar(new_data,
			    AVL_NODE2DATA(node, tree->avl_offset));
			//ASSERT(-1 <= diff && diff <= 1);
			//ASSERT(diff != 0);
			//ASSERT(diff > 0 ? child == 1 : child == 0);
#endif
			node = node->avl_child[child];
		}
#ifdef DEBUG
		diff = tree->avl_compar(new_data,
		    AVL_NODE2DATA(node, tree->avl_offset));
		//ASSERT(-1 <= diff && diff <= 1);
		//ASSERT(diff != 0);
		//ASSERT(diff > 0 ? child == 1 : child == 0);
#endif
	}
	//ASSERT(node->avl_child[child] == NULL);

	avl_insert(tree, new_data, AVL_MKINDEX(node, child));
}
Beispiel #4
0
/*
 * Return the highest valued node in a tree or NULL.
 * (rightmost child from root of tree)
 */
void *
avl_last(avl_tree_t *tree)
{
	avl_node_t *node;
	avl_node_t *prev = NULL;
	size_t off = tree->avl_offset;

	for (node = tree->avl_root; node != NULL; node = node->avl_child[1])
		prev = node;

	if (prev != NULL)
		return (AVL_NODE2DATA(prev, off));
	return (NULL);
}
Beispiel #5
0
/*
 * Return the lowest valued node in a tree or NULL.
 * (leftmost child from root of tree)
 */
void *
avl_first(avl_tree_t *tree)
{
	avl_node_t *node;
	avl_node_t *prev = NULL;
	unsigned int off = tree->avl_offset;

	for (node = tree->avl_root; node != NULL; node = node->avl_child[0])
		prev = node;

	if (prev != NULL)
		return (AVL_NODE2DATA(prev, off));
	return (NULL);
}
Beispiel #6
0
/*
 * Access the node immediately before or after an insertion point.
 *
 * "avl_index_t" is a (avl_node_t *) with the bottom bit indicating a child
 *
 * Return value:
 *	NULL: no node in the given direction
 *	"void *"  of the found tree node
 */
void *
avl_nearest(avl_tree_t *tree, avl_index_t where, int direction)
{
	int child = AVL_INDEX2CHILD(where);
	avl_node_t *node = AVL_INDEX2NODE(where);
	void *data;
	size_t off = tree->avl_offset;

	if (node == NULL) {
		return (NULL);
	}
	data = AVL_NODE2DATA(node, off);
	if (child != direction)
		return (data);

	return (avl_walk(tree, data, direction));
}
Beispiel #7
0
/*
 * Walk from one node to the previous valued node (ie. an infix walk
 * towards the left). At any given node we do one of 2 things:
 *
 * - If there is a left child, go to it, then to it's rightmost descendant.
 *
 * - otherwise we return thru parent nodes until we've come from a right child.
 *
 * Return Value:
 * NULL - if at the end of the nodes
 * otherwise next node
 */
void *
avl_walk(avl_tree_t *tree, void	*oldnode, int left)
{
	size_t off = tree->avl_offset;
	avl_node_t *node = AVL_DATA2NODE(oldnode, off);
	int right = 1 - left;
	int was_child;


	/*
	 * nowhere to walk to if tree is empty
	 */
	if (node == NULL)
		return (NULL);

	/*
	 * Visit the previous valued node. There are two possibilities:
	 *
	 * If this node has a left child, go down one left, then all
	 * the way right.
	 */
	if (node->avl_child[left] != NULL) {
		for (node = node->avl_child[left];
		    node->avl_child[right] != NULL;
		    node = node->avl_child[right])
			;
	/*
	 * Otherwise, return thru left children as far as we can.
	 */
	} else {
		for (;;) {
			was_child = AVL_XCHILD(node);
			node = AVL_XPARENT(node);
			if (node == NULL)
				return (NULL);
			if (was_child == right)
				break;
		}
	}

	return (AVL_NODE2DATA(node, off));
}
Beispiel #8
0
/*
 * Access the node immediately before or after an insertion point.
 *
 * "avl_index_t" is a (avl_node_t *) with the bottom bit indicating a child
 *
 * Return value:
 *	NULL: no node in the given direction
 *	"void *"  of the found tree node
 */
void *
avl_nearest(avl_tree_t *tree, avl_index_t where, int direction)
{
	int child = AVL_INDEX2CHILD(where);
	avl_node_t *node = AVL_INDEX2NODE(where);
	void *data;
	size_t off = tree->avl_offset;

	if (node == NULL) {
		if (tree->avl_root != NULL)
			filebench_log(LOG_ERROR,
			    "Null Node Pointer Supplied");
		return (NULL);
	}
	data = AVL_NODE2DATA(node, off);
	if (child != direction)
		return (data);

	return (avl_walk(tree, data, direction));
}