redblack_test.c 5.4 KB
Newer Older
S
stevenj 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* Copyright (c) 2007-2008 Massachusetts Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 */

23 24
#include <stdio.h>
#include <stdlib.h>
25
#include <math.h>
26 27 28
#include <time.h>
#include "redblack.h"

29
static int comp(rb_key k1, rb_key k2)
30
{
31 32 33
     if (*k1 < *k2) return -1;
     if (*k1 > *k2) return +1;
     return 0;
34 35 36 37 38 39
}

int main(int argc, char **argv)
{
     int N, M;
     int *k;
40
     double kd;
41 42 43 44
     rb_tree t;
     rb_node *n;
     int i, j;

45 46
     if (argc < 2) {
	  fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n");
47 48 49 50 51
	  return 1;
     }

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

54
     srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL)));
55
     for (i = 0; i < N; ++i) {
56 57 58
	  double *newk = (double *) malloc(sizeof(double));
	  *newk = (k[i] = rand() % N);
	  if (!rb_tree_insert(&t, newk)) {
59 60 61 62 63 64 65 66 67
	       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;
	  }
     }
     
68 69 70 71 72 73 74 75
     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)) {
76 77 78
	       fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
	       return 1;
	  }
79 80
     }
 
81 82 83 84 85 86
     n = rb_tree_min(&t);
     for (i = 0; i < N; ++i) {
	  if (!n) {
	       fprintf(stderr, "not enough successors %d\n!", i);
	       return 1;
	  }
87 88
	  printf("%d: %g\n", i, n->k[0]);
	  n = rb_tree_succ(n);
89 90 91 92 93 94 95 96 97 98 99 100
     }
     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;
	  }
101 102
	  printf("%d: %g\n", i, n->k[0]);
	  n = rb_tree_pred(n);
103 104 105 106 107 108 109
     }
     if (n) {
	  fprintf(stderr, "too many predecessors!\n");
	  return 1;
     }
     
     for (M = N; M > 0; --M) {
110 111
	  int knew = rand() % N; /* random new key */
	  j = rand() % M; /* random original key to replace */
112 113 114 115 116
	  for (i = 0; i < N; ++i)
	       if (k[i] >= 0)
		    if (j-- == 0)
			 break;
	  if (i >= N) abort();
117 118
	  kd = k[i];
	  if (!(n = rb_tree_find(&t, &kd))) {
119 120 121
               fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
               return 1;
          }
122
	  n->k[0] = knew;
123 124 125 126 127
	  if (!rb_tree_resort(&t, n)) {
	       fprintf(stderr, "error in rb_tree_resort\n");
	       return 1;
	  }
	  if (!rb_tree_check(&t)) {
128 129
	       fprintf(stderr, "rb_tree_check_failed after change %d!\n",
		       N - M + 1);
130 131 132 133 134
	       return 1;
	  }
	  k[i] = -1 - knew;
     }

S
stevenj 已提交
135 136 137 138 139
     if (t.N != N) {
	  fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
	  return 1;
     }

140 141 142
     for (i = 0; i < N; ++i)
	  k[i] = -1 - k[i]; /* undo negation above */
	  
S
stevenj 已提交
143
     for (i = 0; i < N; ++i) {
144 145 146 147 148 149 150 151 152
	  rb_node *le, *gt;
	  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);
	  double lek = le ? le->k[0] : -HUGE_VAL;
	  double gtk = gt ? gt->k[0] : +HUGE_VAL;
	  printf("%g <= %g < %g\n", lek, kd, gtk);
	  if (n->k[0] > kd) {
S
stevenj 已提交
153
	       if (le) {
154
		    fprintf(stderr, "found invalid le %g for %g\n", lek, kd);
S
stevenj 已提交
155 156 157
		    return 1;
	       }
	       if (gt != n) {
158
		    fprintf(stderr, "gt is not first node for k=%g\n", kd);
S
stevenj 已提交
159 160 161 162 163 164 165
		    return 1;
	       }
	  }
	  else {
	       rb_node *succ = n;
	       do {
		    n = succ;
166 167
		    succ = rb_tree_succ(n);
	       } while (succ && succ->k[0] <= kd);
S
stevenj 已提交
168
	       if (n != le) {
169 170
		    fprintf(stderr,
			    "rb_tree_find_le gave wrong result for k=%g\n",kd);
S
stevenj 已提交
171 172 173
		    return 1;
	       }
	       if (succ != gt) {
174 175
		    fprintf(stderr,
			    "rb_tree_find_gt gave wrong result for k=%g\n",kd);
S
stevenj 已提交
176 177 178 179
		    return 1;
	       }
	  }
     }
180 181 182 183 184 185 186 187
     
     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();
188 189
	  kd = k[i];
	  if (!(n = rb_tree_find(&t, &kd))) {
190 191 192
	       fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
	       return 1;
	  }
193 194 195
	  n = rb_tree_remove(&t, n);
	  free(n->k); 
	  free(n);
196 197 198 199 200 201 202
	  if (!rb_tree_check(&t)) {
	       fprintf(stderr, "rb_tree_check_failed after remove!\n");
	       return 1;
	  }
	  k[i] = -1 - k[i];
     }
     
203 204 205 206 207
     if (t.N != 0) {
	  fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N);
	  return 1;
     }

208 209
     rb_tree_destroy(&t);
     free(k);
S
stevenj 已提交
210 211

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