19 # define TREE_CHECK avltree_check
20 # define TREE_HEIGHT avltree_height
21 # define TREE_LOOKUP avltree_lookup
22 # define TREE_PROBE avltree_probe
23 # define TREE_INITITER avltree_inititer
24 # define TREE_NEXT avltree_next
25 # define TREE_FIRSTPATH avltree_firstpath
26 # define TREE_LASTPATH avltree_lastpath
27 # define TREE_NEXTPATH avltree_nextpath
28 # define TREE_PREVPATH avltree_prevpath
29 # define TREE_INSERT avltree_insert
30 # define TREE_REMOVE avltree_remove
31 # define TREE_JOIN avltree_join
32 # define TREE_SPLIT avltree_split
33 # define TREE_SPLITAT avltree_splitat
34 # define TREE_UNISECT avltree_unisect
35 # define TREE_DIFFSECT avltree_diffsect
41 # define TREE_CHECK rbtree_check
42 # define TREE_HEIGHT rbtree_height
43 # define TREE_LOOKUP rbtree_lookup
44 # define TREE_PROBE rbtree_probe
45 # define TREE_INITITER rbtree_inititer
46 # define TREE_NEXT rbtree_next
47 # define TREE_FIRSTPATH rbtree_firstpath
48 # define TREE_LASTPATH rbtree_lastpath
49 # define TREE_NEXTPATH rbtree_nextpath
50 # define TREE_PREVPATH rbtree_prevpath
51 # define TREE_INSERT rbtree_insert
52 # define TREE_REMOVE rbtree_remove
53 # define TREE_JOIN rbtree_join
54 # define TREE_SPLIT rbtree_split
55 # define TREE_SPLITAT rbtree_splitat
56 # define TREE_UNISECT rbtree_unisect
57 # define TREE_DIFFSECT rbtree_diffsect
59 # include "splaytree.h"
63 # error "unknown `TREE' value"
77 static unsigned long nodeseq = 0;
79 static int my_ordnav(struct bstree_nodecls *cls,
80 const struct bstnode *node, void *arg)
82 const struct my_node *mynode = (const struct my_node *)node;
85 if (*key < mynode->k) return (-1);
86 else if (*key > mynode->k) return (+1);
90 static void my_upd(struct bstree_nodecls *cls, struct bstnode *node)
93 *mynode = (struct my_node *)node,
94 *left = (struct my_node *)mynode->_n._bst.left,
95 *right = (struct my_node *)mynode->_n._bst.right;
97 mynode->n = (left ? left->n : 0) + (right ? right->n : 0) + 1;
100 static const void *my_key(struct bstree_nodecls *cls,
101 const struct bstnode *node)
103 const struct my_node *mynode = (const struct my_node *)node;
107 static int my_check(struct bstree_nodecls *cls,
108 struct bstnode *const *root,
109 const struct bstnode *parent,
110 const struct bstnode *lbound,
111 const struct bstnode *rbound,
112 const struct bstnode *node, unsigned ord,
115 struct my_node *mynode, *left, *right;
119 if (ord == BSTCHK_BEFORE) {
120 mynode = (struct my_node *)node;
121 left = (struct my_node *)mynode->_n._bst.left;
122 right = (struct my_node *)mynode->_n._bst.right;
123 want = (left ? left->n : 0) + (right ? right->n : 0) + 1;
124 if (mynode->n != want) {
125 fprintf(stderr, "MY_TREE %p BUG: node #%08lx %lu count %lu /= %lu\n",
126 (void *)root, mynode->seq, mynode->k,
127 (unsigned long)mynode->n, (unsigned long)want);
132 if (bstree_chkorder(cls, root, parent, lbound, rbound, node, ord, arg))
138 static void my_ident(struct bstree_nodecls *cls,
139 const struct bstnode *node, FILE *fp)
141 const struct my_node *my_node = (const struct my_node *)node;
142 fprintf(fp, "#0x%08lx %lu", my_node->seq, my_node->k);
145 static const struct bstree_nodeops my_ordops =
146 { my_ordnav, my_upd, my_key, my_check, my_ident };
148 static void bail(const char *msg, ...)
153 va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);
155 if (pos >= 0) fprintf(stderr, " (input pos = %ld)", pos);
160 static struct my_node *make_node(unsigned long k)
162 struct my_node *node;
164 node = malloc(sizeof(*node));
165 if (!node) bail("out of memory");
166 node->_n.f = 0; node->n = 1; node->seq = nodeseq++; node->k = k;
171 static const char balch[3] = { '=', '-', '+' };
174 static void dump_recurse(const struct my_node *node, int indent)
178 if (node->_n.f&RBF_RED) indent++;
179 else indent = (indent + 2)&~1;
183 dump_recurse((const struct my_node *)node->_n._bst.left, indent);
184 printf("\t#0x%08lx (n = %3lu)\t%*s",
185 node->seq, (unsigned long)node->n, 4*indent, "");
187 printf("(%c)", balch[node->_n.f&AVLF_BALMASK]);
189 printf("(%c)", node->_n.f&RBF_RED ? ' ' : '*');
191 fputs("(*)", stdout);
193 printf(" %lu\n", node->k);
194 dump_recurse((const struct my_node *)node->_n._bst.right, indent);
197 void dump_tree(const struct bstnode *root, int ht)
199 printf("tree dump, ht = %d\n", ht);
200 if (!root) printf("\t(tree empty)\n");
201 else dump_recurse((const struct my_node *)root, -1);
204 static void list_recurse(const struct my_node *node)
210 list_recurse((const struct my_node *)node->_n._bst.left);
213 if (!(node->_n.f&RBF_RED)) putchar('*');
215 printf("%lu", node->k);
217 list_recurse((const struct my_node *)node->_n._bst.right);
222 static void list_tree(struct bstnode *root)
223 { list_recurse((struct my_node *)root); putchar('\n'); }
225 static struct bstnode *copy_tree(const struct my_node *node)
227 struct my_node *copy;
229 if (!node) return (0);
230 copy = make_node(node->k);
231 #if TREE == AVL || TREE == RB
232 copy->_n.f = node->_n.f;
235 copy_tree((const struct my_node *)node->_n._bst.left);
236 copy->_n._bst.right =
237 copy_tree((const struct my_node *)node->_n._bst.right);
239 return (©->_n._bst);
242 static unsigned long read_int(void)
247 do ch = getchar(); while (isspace(ch));
248 if (!isdigit(ch)) bail("integer expected, found `%c'", ch);
250 if (scanf("%lu", &k) != 1) bail("integer expected, scanf failed");
254 static struct bstnode *read_tree(int *ht_out)
256 struct my_node *node, *left, *right;
263 unsigned f = RBF_RED;
266 do ch = getchar(); while (isspace(ch));
267 if (ch == '_') { *ht_out = 0; return (0); }
268 else if (ch != '(') bail("expected `(', found `%c'", ch);
269 left = (struct my_node *)read_tree(&lht);
271 do ch = getchar(); while (isspace(ch));
273 if (ch == '*') f &= ~RBF_RED;
278 ungetc(ch, stdin); k = read_int();
279 right = (struct my_node *)read_tree(&rht);
280 do ch = getchar(); while (isspace(ch));
281 if (ch != ')') bail("expected `)', found `%c'", ch);
284 node->_n._bst.left = left ? &left->_n._bst : 0;
285 node->_n._bst.right = right ? &right->_n._bst : 0;
286 node->n = (left ? left->n : 0) + (right ? right->n : 0) + 1;
289 case -1: f = AVLBAL_LBIAS; ht = lht + 1; break;
290 case 0: f = AVLBAL_EVEN; ht = lht + 1; break;
291 case +1: f = AVLBAL_RBIAS; ht = rht + 1; break;
292 default: bail("tree is not AVL");
296 if (lht != rht) bail("tree is not red-black");
297 ht = f&RBF_RED ? lht : lht + 1;
300 if (lht >= rht) ht = lht + 1;
304 return (&node->_n._bst);
307 static void free_tree(struct bstnode **root)
309 struct my_node *node;
312 TREE_INITITER(*root, &it);
314 node = TREE_NEXT(&it); if (!node) break;
324 struct bstree_nodecls ordcls;
325 struct { struct bstnode *root; int ht; } cur, stack[NSTACK], u;
326 struct my_node *node = 0, *t;
327 struct bstnode **link;
331 unsigned long i, j, k;
338 cur.root = 0; cur.ht = 0; ordcls.ops = &my_ordops;
341 do ch = getchar(); while (isspace(ch));
347 case ';': /* comment */
348 do ch = getchar(); while (ch != EOF && ch != '\n');
351 case ':': /* print message */
353 ch = getchar(); if (ch == '\n' || ch == EOF) break;
364 case '+': /* insert */
365 if (!(f&f_key)) bail("no key");
366 if (!(f&f_path)) node = TREE_PROBE(&ordcls, &cur.root, &k, &path);
367 if (node) bail("key %lu already present", k);
368 cur.ht += TREE_INSERT(&ordcls, &path, &make_node(k)->_n);
369 f &= ~(f_key | f_path | f_dumped);
374 case '-': /* remove */
376 if (!node) bail("path empty");
378 if (!(f&f_key)) bail("no key or path");
379 node = TREE_PROBE(&ordcls, &cur.root, &k, &path);
380 if (!node) bail("key %lu not present", k);
382 cur.ht += TREE_REMOVE(&ordcls, &path);
383 free(node); node = 0; f &= ~(f_key | f_path | f_dumped);
388 case '#': /* populate */
390 do ch = getchar(); while (isspace(ch));
391 if (ch == '-') j = read_int();
392 else { ungetc(ch, stdin); j = i; i = 1; }
394 if (!TREE_PROBE(&ordcls, &cur.root, &i, &path))
395 cur.ht += TREE_INSERT(&ordcls, &path, &make_node(i)->_n);
400 node = 0; f &= ~(f_key | f_path | f_dumped);
404 case '?': /* lookup */
405 if (!(f&f_key)) bail("no key");
406 node = TREE_LOOKUP(&ordcls, cur.root, &k); f &= ~(f_key | f_path);
409 case '@': /* probe */
410 if (!(f&f_key)) bail("no key");
411 node = TREE_PROBE(&ordcls, &cur.root, &k, &path);
415 case '[': /* first */
416 node = TREE_FIRSTPATH(&cur.root, &path);
417 if (!node) f &= ~(f_key | f_path);
418 else { k = node->k; f |= f_key | f_path; }
422 node = TREE_LASTPATH(&cur.root, &path);
423 if (!node) f &= ~(f_key | f_path);
424 else { k = node->k; f |= f_key | f_path; }
427 case '<': /* previous */
428 if (!(f&f_path)) bail("no path");
429 node = TREE_PREVPATH(&path);
430 if (!node) f &= ~(f_key | f_path);
431 else { k = node->k; f |= f_key | f_path; }
435 if (!(f&f_path)) bail("no path");
436 node = TREE_NEXTPATH(&path);
437 if (!node) f &= ~(f_key | f_path);
438 else { k = node->k; f |= f_key | f_path; }
441 case '*': /* clear */
442 node = 0; f &= ~(f_key | f_path);
446 if (sp >= NSTACK) bail("stack full");
447 stack[sp++] = cur; cur.root = 0; cur.ht = 0;
448 node = 0; f &= ~(f_key | f_path | f_dumped);
451 case '"': /* duplicate */
452 if (sp >= NSTACK) bail("stack full");
454 cur.root = copy_tree((struct my_node *)cur.root);
455 node = 0; f &= ~(f_key | f_path | f_dumped);
459 if (!sp) bail("stack empty");
460 free_tree(&cur.root); cur = stack[--sp];
461 node = 0; f &= ~(f_key | f_path | f_dumped);
465 if (!sp) bail("stack empty");
466 u = stack[sp - 1]; stack[sp - 1] = cur; cur = u;
467 node = 0; f &= ~(f_key | f_path | f_dumped);
472 if (!sp) bail("stack empty");
473 if (!(f&f_key)) t = 0;
474 else t = make_node(k);
475 cur.ht = TREE_JOIN(&ordcls, &cur.root,
476 &stack[sp - 1].root, stack[sp - 1].ht,
479 sp--; node = 0; f &= ~(f_key | f_path | f_dumped);
484 case '/': /* split */
485 if (sp > NSTACK - 2) bail("stack full");
486 if (!(f&f_path)) bail("no path");
487 node = TREE_SPLIT(&ordcls, &stack[sp].root, &stack[sp].ht,
491 if (node) node->n = 1;
492 stack[sp + 1].root = &node->_n._bst;
493 sp += 2; f &= ~(f_key | f_path | f_dumped);
498 case '|': /* union/intersection */
499 if (!sp) bail("stack empty");
500 TREE_UNISECT(&ordcls, &cur.root, &cur.ht,
501 &stack[sp - 1].root, &stack[sp - 1].ht,
502 &stack[sp - 1].root, stack[sp - 1].ht,
504 node = 0; f &= ~(f_key | f_path | f_dumped);
509 case '\\': /* difference/intersection */
510 if (!sp) bail("stack empty");
511 if (sp >= NSTACK) bail("stack full");
512 TREE_DIFFSECT(&ordcls,
514 &stack[sp].root, &stack[sp].ht,
516 &stack[sp - 1].root);
517 sp++; node = 0; f &= ~(f_key | f_path | f_dumped);
521 case 'k': /* print key */
522 if (f&f_key) printf("%lu\n", k);
523 else fputs("(no key)\n", stdout);
526 case 'n': /* print node */
527 if (!node) fputs("(nil)\n", stdout);
528 else printf("#<node #0x%08lx %lu>\n", node->seq, node->k);
531 case 'p': /* print path */
536 for (i = 0, t = 0; i <= path.k; i++) {
539 if (!t && link == &cur.root)
540 fputs("#<link root -> ", stdout);
541 else if (t && link == &t->_n._bst.left)
542 printf("#<link node #0x%08lx %lu left -> ", t->seq, t->k);
543 else if (t && link == &t->_n._bst.right)
544 printf("#<link node #0x%08lx %lu right -> ", t->seq, t->k);
546 printf("#<link address %p -> ", (void *)link);
547 t = (struct my_node *)*link;
548 if (!t) fputs("(nil)", stdout);
549 else printf("node #0x%08lx %lu", t->seq, t->k);
552 putchar(')'); putchar('\n');
556 case 'i': /* iterate */
557 TREE_INITITER(cur.root, &it); f |= f_first;
559 t = TREE_NEXT(&it); if (!t) break;
560 if (f&f_first) f &= ~f_first;
564 if (f&f_first) fputs("(empty tree)", stdout);
573 dump_tree(cur.root, cur.ht); f |= f_dumped;
576 case '!': /* check */
577 if (TREE_CHECK(&ordcls, &cur.root, cur.ht, 0)) {
579 fputs("offending tree...\n", stdout);
580 dump_tree(cur.root, cur.ht); fflush(stdout);
582 bail("check failed");
586 case '=': /* assign */
587 free_tree(&cur.root);
588 cur.root = read_tree(&cur.ht);
592 if (isdigit(ch)) { /* set key */
594 if (scanf("%lu", &k) != 1) bail("integer expected, scanf failed");
598 bail("unexpected character `%c'", ch);
602 if (ferror(stdout)) bail("stdout write failed: %s\n", strerror(errno));
605 if (sp) bail("stack not empty");
606 free_tree(&cur.root);