Exemple #1
0
void rbtree_remove(struct rbtree_node *node, struct rbtree *tree)
{
	struct rbtree_node *parent = get_parent(node);
	struct rbtree_node *left = node->left;
	struct rbtree_node *right = node->right;
	struct rbtree_node *next;
	enum rb_color color;

	if (node == tree->first)
		tree->first = rbtree_next(node);
	if (node == tree->last)
		tree->last = rbtree_prev(node);

	if (!left)
		next = right;
	else if (!right)
		next = left;
	else
		next = get_first(right);

	if (parent)
		set_child(next, parent, parent->left == node);
	else
		tree->root = next;

	if (left && right) {
		color = get_color(next);
		set_color(get_color(node), next);

		next->left = left;
		set_parent(next, left);

		if (next != right) {
			parent = get_parent(next);
			set_parent(get_parent(node), next);

			node = next->right;
			parent->left = node;

			next->right = right;
			set_parent(next, right);
		} else {
			set_parent(parent, next);
			parent = next;
			node = next->right;
		}
	} else {
		color = get_color(node);
		node = next;
	}
	/*
	 * 'node' is now the sole successor's child and 'parent' its
	 * new parent (since the successor can have been moved).
	 */
	if (node)
		set_parent(parent, node);

	/*
	 * The 'easy' cases.
	 */
	if (color == RB_RED)
		return;
	if (node && is_red(node)) {
		set_color(RB_BLACK, node);
		return;
	}

	do {
		if (node == tree->root)
			break;

		if (node == parent->left) {
			struct rbtree_node *sibling = parent->right;

			if (is_red(sibling)) {
				set_color(RB_BLACK, sibling);
				set_color(RB_RED, parent);
				rotate_left(parent, tree);
				sibling = parent->right;
			}
			if ((!sibling->left || is_black(sibling->left))
			    && (!sibling->right || is_black(sibling->right))) {
				set_color(RB_RED, sibling);
				node = parent;
				parent = get_parent(parent);
				continue;
			}
			if (!sibling->right || is_black(sibling->right)) {
				set_color(RB_BLACK, sibling->left);
				set_color(RB_RED, sibling);
				rotate_right(sibling, tree);
				sibling = parent->right;
			}
			set_color(get_color(parent), sibling);
			set_color(RB_BLACK, parent);
			set_color(RB_BLACK, sibling->right);
			rotate_left(parent, tree);
			node = tree->root;
			break;
		} else {
			struct rbtree_node *sibling = parent->left;

			if (is_red(sibling)) {
				set_color(RB_BLACK, sibling);
				set_color(RB_RED, parent);
				rotate_right(parent, tree);
				sibling = parent->left;
			}
			if ((!sibling->left || is_black(sibling->left))
			    && (!sibling->right || is_black(sibling->right))) {
				set_color(RB_RED, sibling);
				node = parent;
				parent = get_parent(parent);
				continue;
			}
			if (!sibling->left || is_black(sibling->left)) {
				set_color(RB_BLACK, sibling->right);
				set_color(RB_RED, sibling);
				rotate_left(sibling, tree);
				sibling = parent->left;
			}
			set_color(get_color(parent), sibling);
			set_color(RB_BLACK, parent);
			set_color(RB_BLACK, sibling->left);
			rotate_right(parent, tree);
			node = tree->root;
			break;
		}
	} while (is_black(node));

	if (node)
		set_color(RB_BLACK, node);
}
Exemple #2
0
int router_nearest(struct router_t* router, const uint8_t id[N_NODEID], struct node_t* nodes[], size_t count)
{
	int i, min, diff;
	uint8_t xor[N_NODEID];
	heap_t* heap;
	struct rbitem_t* item;
	struct rbtree_node_t* node;
	const struct rbtree_node_t* prev;
	const struct rbtree_node_t* next;

	heap = heap_create(node_compare_less, (void*)id);
	heap_reserve(heap, count + 1);

	min = N_BITS;
	locker_lock(&router->locker);
	rbtree_find(&router->rbtree, id, &node);
	if (NULL == node)
	{
		locker_unlock(&router->locker);
		return 0;
	}

	item = rbtree_entry(node, struct rbitem_t, link);
	bitmap_xor(xor, id, item->node->id, N_BITS);
	diff = bitmap_count_leading_zero(xor, N_BITS);
	min = min < diff ? min : diff;
	heap_push(heap, item->node);

	prev = rbtree_prev(node);
	next = rbtree_next(node);
	do
	{
		while (prev)
		{
			item = rbtree_entry(prev, struct rbitem_t, link);
			bitmap_xor(xor, id, item->node->id, N_BITS);
			diff = bitmap_count_leading_zero(xor, N_BITS);
			heap_push(heap, item->node);
			if (heap_size(heap) > (int)count)
				heap_pop(heap);

			prev = rbtree_prev(prev);
			if (diff < min)
			{
				min = diff;
				break; // try right
			}
		}

		while (next)
		{
			item = rbtree_entry(next, struct rbitem_t, link);
			bitmap_xor(xor, id, item->node->id, N_BITS);
			diff = bitmap_count_leading_zero(xor, N_BITS);
			heap_push(heap, item->node);
			if (heap_size(heap) > (int)count)
				heap_pop(heap);

			next = rbtree_next(next);
			if (diff < min)
			{
				min = diff;
				break; // try left
			}
		}
	} while (heap_size(heap) < (int)count && (prev || next));

	for (i = 0; i < (int)count && !heap_empty(heap); i++)
	{
		nodes[i] = heap_top(heap);
		node_addref(nodes[i]);
		heap_pop(heap);
	}

	locker_unlock(&router->locker);
	heap_destroy(heap);
	return i;
}