rbtest.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include "../sti.h"
  7. #include <time.h>
  8. double getCurrentTime() { // in seconds
  9. double now;
  10. struct timespec ts;
  11. static double offset = 0;
  12. // CLOCK_MONOTONIC_RAW is linux-specific.
  13. clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
  14. now = (double)ts.tv_sec + ((double)ts.tv_nsec / 1000000000.0);
  15. if(offset == 0) offset = now;
  16. return now - offset;
  17. }
  18. int rb_is_red(rb_node* n);
  19. int check_double_red(rb_node* n) {
  20. if(!n) return 0;
  21. if(rb_is_red(n)) {
  22. if(n->kids[0] && rb_is_red(n->kids[0])) goto BAD;
  23. if(n->kids[1] && rb_is_red(n->kids[1])) goto BAD;
  24. }
  25. return check_double_red(n->kids[0]) + check_double_red(n->kids[1]);
  26. BAD:
  27. printf("\n!!! ---- double red at %s -----\n\n", n->key);
  28. return 1;
  29. }
  30. int check_black_height(rb_node* n, int* bad) {
  31. if(!n) return 1;
  32. int a = check_black_height(n->kids[0], bad);
  33. int b = check_black_height(n->kids[1], bad);
  34. if(a != b) {
  35. printf("\n\n!!! --- height mismatch at %s --------------\n\n", n->key);
  36. *bad = 1;
  37. }
  38. return a + !rb_is_red(n);
  39. }
  40. char rand_char() {
  41. static char* chars = "QWERTYUIOPASDFGHJKLZXCVBNM";
  42. return chars[rand() % 26];
  43. }
  44. char** generate_random_keys(int len) {
  45. char** out = malloc(len * sizeof(*out));
  46. int cl = 0;
  47. for(int i = 0; i < len; i++) {
  48. char* k = malloc(5);
  49. TRY_AGAIN:
  50. k[0] = rand_char();
  51. k[1] = rand_char();
  52. k[2] = rand_char();
  53. k[3] = rand_char();
  54. k[4] = 0;
  55. for(int j = 0; j < cl; j++) {
  56. if(0 == strcmp(k, out[j])) goto TRY_AGAIN;
  57. }
  58. out[i] = k;
  59. }
  60. return out;
  61. }
  62. long test_trav(char* key, void* data, void* user_data) {
  63. printf("%s\n", key);
  64. return 0;
  65. }
  66. int str_sort(const void* a, const void* b) {
  67. char* c = *((char**)a);
  68. char* d = *((char**)b);
  69. return strcmp(c, d);
  70. }
  71. void test_tree(int len) {
  72. RB(int) t;
  73. t.tree.root = NULL;
  74. int bad = 0;
  75. int val = 5;
  76. char** keys = generate_random_keys(len);
  77. // double start, end;
  78. for(int i = 0; i < len; i++) {
  79. // printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ninserting %s\n", keys[i]);
  80. RB_insert(&t, keys[i], val);
  81. // html_print_node(t.tree.root, get_max_height(t.tree.root)); html_spacer();
  82. check_black_height(t.tree.root, &bad);
  83. if(bad) {
  84. printf("black height mismatch\n");
  85. fprintf(dbg, "black height mismatch\n");
  86. html_print_node(t.tree.root, get_max_height(t.tree.root)); html_spacer();
  87. html_footer();
  88. exit(1);
  89. }
  90. if(check_double_red(t.tree.root)) {
  91. printf("double red found\n");
  92. html_footer();
  93. exit(1);
  94. }
  95. }
  96. for(int i = 0; i < len; i++) {
  97. // printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ndeleting %s\n", keys[i]);
  98. // fprintf(dbg, "Deleted %s\n", keys[i]);
  99. RB_delete(&t, keys[i], NULL);
  100. // printf("-------deletion complete\n");
  101. // printf(".root: %p\n", t.tree.root);
  102. // html_print_node(t.tree.root, get_max_height(t.tree.root)); html_spacer();
  103. // fflush(dbg);
  104. check_black_height(t.tree.root, &bad);
  105. if(bad) {
  106. fprintf(dbg, "black height mismatch\n");
  107. html_print_node(t.tree.root, get_max_height(t.tree.root)); html_spacer();
  108. html_footer();
  109. printf("black height mismatch\n");
  110. exit(1);
  111. }
  112. if(check_double_red(t.tree.root)) {
  113. printf("double red found\n");
  114. html_footer();
  115. exit(1);
  116. }
  117. }
  118. RB_trunc(&t);
  119. }
  120. void hash_race(int len, int htinit) {
  121. double start, end;
  122. RB(int) t;
  123. RB_init(&t);
  124. int val = 5;
  125. HT(int) ht;
  126. HT_init(&ht, htinit);
  127. char** keys = generate_random_keys(len);
  128. printf("N = %d, hash initial size = %d\n", len, htinit);
  129. printf("Inserts:\n");
  130. start = getCurrentTime();
  131. for(int i = 0; i < len; i++) {
  132. RB_insert(&t, keys[i], val);
  133. }
  134. end = getCurrentTime();
  135. printf(" Red-Black Tree: %fms\n", (end - start)* 1000);
  136. start = getCurrentTime();
  137. for(int i = 0; i < len; i++) {
  138. HT_set(&ht, keys[i], val);
  139. }
  140. end = getCurrentTime();
  141. printf(" Hash Table: %fms\n", (end - start)* 1000);
  142. //---------------------------------
  143. printf("Finds:\n");
  144. start = getCurrentTime();
  145. for(int i = 0; i < len; i++) {
  146. RB_find(&t, keys[i], NULL);
  147. }
  148. end = getCurrentTime();
  149. printf(" Red-Black Tree: %fms\n", (end - start)* 1000);
  150. start = getCurrentTime();
  151. for(int i = 0; i < len; i++) {
  152. HT_get(&ht, keys[i], &val);
  153. }
  154. end = getCurrentTime();
  155. printf(" Hash Table: %fms\n", (end - start)* 1000);
  156. //---------------------------------
  157. printf("Deletes:\n");
  158. start = getCurrentTime();
  159. for(int i = 0; i < len; i++) {
  160. RB_delete(&t, keys[i], NULL);
  161. }
  162. end = getCurrentTime();
  163. printf(" Red-Black Tree: %fms\n", (end - start)* 1000);
  164. start = getCurrentTime();
  165. for(int i = 0; i < len; i++) {
  166. HT_delete(&ht, keys[i]);
  167. }
  168. end = getCurrentTime();
  169. printf(" Hash Table: %fms\n", (end - start)* 1000);
  170. printf("\n\n");
  171. }
  172. int main(int argc, char* argv[]) {
  173. html_header("./debug.html");
  174. // test_tree(100000);
  175. // hash_race(strtol(argv[1], NULL, 10), strtol(argv[2], NULL, 10) );
  176. hash_race(100, 128);
  177. hash_race(1000, 128);
  178. hash_race(10000, 128);
  179. hash_race(100000, 128);
  180. hash_race(1000000, 128);
  181. //*/
  182. /*
  183. rb_tree_ t;
  184. t.root = NULL;
  185. int val = 5;
  186. for(int i = 0; i < 12; i++) {
  187. rb_insert_(&t, Qkeys[i], &val);
  188. fprintf(f, "i: %d\n", i);
  189. html_print_node(t.root, get_max_height(t.root)); html_spacer();
  190. check_black_height(t.root);
  191. print_tree(t.root, 0);
  192. printf("\n\n");
  193. }
  194. rb_delete(&t, "V", NULL);
  195. // rb_delete(&t, "N", NULL);
  196. // rb_delete(&t, "Ra", NULL);
  197. html_print_node(t.root, get_max_height(t.root)); html_spacer();
  198. fprintf(f, "Deleting\n");
  199. printf("----------\n");
  200. rb_delete(&t, "Z", NULL);
  201. html_print_node(t.root, get_max_height(t.root)); html_spacer();
  202. */
  203. html_footer();
  204. // printf("depth: %d\n", get_depth(t.root));
  205. // print_level(t.root, 0, 0); printf("\n");
  206. // print_level_lines(t.root, 0, 0); printf("\n");
  207. // print_level(t.root, 1, 0); printf("\n");
  208. // print_level_lines(t.root, 1, 0); printf("\n");
  209. // print_level(t.root, 2, 0); printf("\n");
  210. // print_level_lines(t.root, 2, 0); printf("\n");
  211. // print_level(t.root, 3, 0); printf("\n");
  212. // // print_level_lines(t.root, 3, 0);
  213. // print_level(t.root, 4, 0);
  214. printf("\n\n");
  215. return 0;
  216. }