Esempio n. 1
0
int rb_tree_check(struct rb_tree* tree, struct rb_node* node)
{
	int lh, rh;

	if (node == NULL)
		return 1;
	else
	{
		struct rb_node *ln = node->link[0];
		struct rb_node *rn = node->link[1];

		/* Consecutive red links */
		if (is_red(node)) {
			if (is_red(ln) || is_red(rn))
			{
				puts("Red violation");
				return 0;
			}
		}

		lh = rb_tree_check(tree, ln);
		rh = rb_tree_check(tree, rn);

		/* Invalid binary search tree - not sorted correctly */
		if ((ln && tree->compare(ln->key, node->key) >= 0) || (rn && tree->compare(rn->key, node->key) <= 0))
		{
			puts("Binary tree violation");
			return 0;
		}

		/* Black height mismatch */
		if ( lh != 0 && rh != 0 && lh != rh ) {
			puts ( "Black violation" );
			return 0;
		}

		/* Only count black links */
		if (lh != 0 && rh != 0)
			return is_red(node) ? lh : lh + 1;
		else
			return 0;
	}
}
Esempio n. 2
0
int rb_tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
	struct rb_node* node;
	if (tree_search(tree, key))
		return 0;
	node = rb_tree_insert_r(tree, tree->root, key, value);
	tree->root = node;
	tree->root->red = 0;
	tree->elements++;
#ifdef RB_TREE_CHECKS
	rb_tree_check(tree, node);
#endif
	return 1;
}
Esempio n. 3
0
int rb_tree_remove_node(struct rb_tree* tree, const void* key, rb_tree_free_node freecb)
{
	struct rb_node head = {0}; /* False tree root */
	struct rb_node *q, *p, *g; /* Helpers */
	struct rb_node *f = NULL;  /* Found item */
	int dir = 1;

	if (!tree->root)
		return 0;

	/* Set up helpers */
	q = &head;
	g = p = NULL;
	q->link[1] = tree->root;

	/* Search and push a red down */
	while (q->link[dir])
	{
		int last = dir;
		int res;

		/* Update helpers */
		g = p, p = q;
		q = q->link[dir];
		res = tree->compare(q->key, key);
		dir = res < 0;

		/* Save found node */
		if (!res)
			f = q;

		/* Push the red node down */
		if (!is_red(q) && !is_red(q->link[dir]))
		{
			if (is_red(q->link[!dir]))
				p = p->link[last] = rb_tree_rotate_single(q, dir);
			else if (!is_red(q->link[!dir]))
			{
				struct rb_node* s = p->link[!last];
				if (s)
				{
					if (!is_red(s->link[!last]) && !is_red (s->link[last]))
					{
						/* Color flip */
						p->red = 0;
						s->red = 1;
						q->red = 1;
					}
					else
					{
						int dir2 = g->link[1] == p;
						if (is_red(s->link[last]))
							g->link[dir2] = rb_tree_rotate_double(p, last);
						else if (is_red(s->link[!last]))
							g->link[dir2] = rb_tree_rotate_single(p, last);

						/* Ensure correct coloring */
						q->red = g->link[dir2]->red = 1;
						g->link[dir2]->link[0]->red = 0;
						g->link[dir2]->link[1]->red = 0;
					}
				}
			}
		}
	}

	/* Replace and remove if found */
	if (f)
	{
		freecb(f);
		f->key = q->key;
		f->value = q->value;
		p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
		tree->free(q);
		tree->elements--;
	 }

	/* Update root and make it black */
	tree->root = head.link[1];
	if (tree->root != NULL)
		tree->root->red = 0;

#ifdef RB_TREE_CHECKS
	rb_tree_check(tree, tree->root);
#endif

	return f != NULL;
}
Esempio n. 4
0
int main(int argc, char **argv)
{
    int N, M;
    int *k;
    double kd;
    rb_tree t;
    rb_node *n;
    int i, j;

    if (argc < 2) {
        fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n");
        return 1;
    }

    N = atoi(argv[1]);
    k = (int *) malloc(N * sizeof(int));
    rb_tree_init(&t, comp);

    srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL)));
    for (i = 0; i < N; ++i) {
        double *newk = (double *) malloc(sizeof(double));
        *newk = (k[i] = rand() % N);
        if (!rb_tree_insert(&t, newk)) {
            fprintf(stderr, "error in rb_tree_insert\n");
            return 1;
        }
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after insert!\n");
            return 1;
        }
    }

    if (t.N != N) {
        fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
        return 1;
    }

    for (i = 0; i < N; ++i) {
        kd = k[i];
        if (!rb_tree_find(&t, &kd)) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
    }

    n = rb_tree_min(&t);
    for (i = 0; i < N; ++i) {
        if (!n) {
            fprintf(stderr, "not enough successors %d\n!", i);
            return 1;
        }
        printf("%d: %g\n", i, n->k[0]);
        n = rb_tree_succ(n);
    }
    if (n) {
        fprintf(stderr, "too many successors!\n");
        return 1;
    }

    n = rb_tree_max(&t);
    for (i = 0; i < N; ++i) {
        if (!n) {
            fprintf(stderr, "not enough predecessors %d\n!", i);
            return 1;
        }
        printf("%d: %g\n", i, n->k[0]);
        n = rb_tree_pred(n);
    }
    if (n) {
        fprintf(stderr, "too many predecessors!\n");
        return 1;
    }

    for (M = N; M > 0; --M) {
        int knew = rand() % N;  /* random new key */
        j = rand() % M;         /* random original key to replace */
        for (i = 0; i < N; ++i)
            if (k[i] >= 0)
                if (j-- == 0)
                    break;
        if (i >= N)
            abort();
        kd = k[i];
        if (!(n = rb_tree_find(&t, &kd))) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
        n->k[0] = knew;
        if (!rb_tree_resort(&t, n)) {
            fprintf(stderr, "error in rb_tree_resort\n");
            return 1;
        }
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after change %d!\n", N - M + 1);
            return 1;
        }
        k[i] = -1 - knew;
    }

    if (t.N != N) {
        fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
        return 1;
    }

    for (i = 0; i < N; ++i)
        k[i] = -1 - k[i];       /* undo negation above */

    for (i = 0; i < N; ++i) {
        rb_node *le, *gt;
        double lek, gtk;
        kd = 0.01 * (rand() % (N * 150) - N * 25);
        le = rb_tree_find_le(&t, &kd);
        gt = rb_tree_find_gt(&t, &kd);
        n = rb_tree_min(&t);
        lek = le ? le->k[0] : -HUGE_VAL;
        gtk = gt ? gt->k[0] : +HUGE_VAL;
        printf("%g <= %g < %g\n", lek, kd, gtk);
        if (n->k[0] > kd) {
            if (le) {
                fprintf(stderr, "found invalid le %g for %g\n", lek, kd);
                return 1;
            }
            if (gt != n) {
                fprintf(stderr, "gt is not first node for k=%g\n", kd);
                return 1;
            }
        } else {
            rb_node *succ = n;
            do {
                n = succ;
                succ = rb_tree_succ(n);
            } while (succ && succ->k[0] <= kd);
            if (n != le) {
                fprintf(stderr, "rb_tree_find_le gave wrong result for k=%g\n", kd);
                return 1;
            }
            if (succ != gt) {
                fprintf(stderr, "rb_tree_find_gt gave wrong result for k=%g\n", kd);
                return 1;
            }
        }
    }

    for (M = N; M > 0; --M) {
        j = rand() % M;
        for (i = 0; i < N; ++i)
            if (k[i] >= 0)
                if (j-- == 0)
                    break;
        if (i >= N)
            abort();
        kd = k[i];
        if (!(n = rb_tree_find(&t, &kd))) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
        n = rb_tree_remove(&t, n);
        free(n->k);
        free(n);
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after remove!\n");
            return 1;
        }
        k[i] = -1 - k[i];
    }

    if (t.N != 0) {
        fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N);
        return 1;
    }

    rb_tree_destroy(&t);
    free(k);

    printf("SUCCESS.\n");
    return 0;
}