]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - tree234.c
Move MODULE files out of individual project directories into a
[PuTTY.git] / tree234.c
1 /*
2  * tree234.c: reasonably generic counted 2-3-4 tree routines.
3  * 
4  * This file is copyright 1999-2001 Simon Tatham.
5  * 
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  * 
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT.  IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <assert.h>
31
32 #include "tree234.h"
33
34 #define smalloc malloc
35 #define sfree free
36
37 #define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )
38
39 #ifdef TEST
40 #define LOG(x) (printf x)
41 #else
42 #define LOG(x)
43 #endif
44
45 typedef struct node234_Tag node234;
46
47 struct tree234_Tag {
48     node234 *root;
49     cmpfn234 cmp;
50 };
51
52 struct node234_Tag {
53     node234 *parent;
54     node234 *kids[4];
55     int counts[4];
56     void *elems[3];
57 };
58
59 /*
60  * Create a 2-3-4 tree.
61  */
62 tree234 *newtree234(cmpfn234 cmp)
63 {
64     tree234 *ret = mknew(tree234);
65     LOG(("created tree %p\n", ret));
66     ret->root = NULL;
67     ret->cmp = cmp;
68     return ret;
69 }
70
71 /*
72  * Free a 2-3-4 tree (not including freeing the elements).
73  */
74 static void freenode234(node234 * n)
75 {
76     if (!n)
77         return;
78     freenode234(n->kids[0]);
79     freenode234(n->kids[1]);
80     freenode234(n->kids[2]);
81     freenode234(n->kids[3]);
82     sfree(n);
83 }
84
85 void freetree234(tree234 * t)
86 {
87     freenode234(t->root);
88     sfree(t);
89 }
90
91 /*
92  * Internal function to count a node.
93  */
94 static int countnode234(node234 * n)
95 {
96     int count = 0;
97     int i;
98     if (!n)
99         return 0;
100     for (i = 0; i < 4; i++)
101         count += n->counts[i];
102     for (i = 0; i < 3; i++)
103         if (n->elems[i])
104             count++;
105     return count;
106 }
107
108 /*
109  * Count the elements in a tree.
110  */
111 int count234(tree234 * t)
112 {
113     if (t->root)
114         return countnode234(t->root);
115     else
116         return 0;
117 }
118
119 /*
120  * Add an element e to a 2-3-4 tree t. Returns e on success, or if
121  * an existing element compares equal, returns that.
122  */
123 static void *add234_internal(tree234 * t, void *e, int index)
124 {
125     node234 *n, **np, *left, *right;
126     void *orig_e = e;
127     int c, lcount, rcount;
128
129     LOG(("adding node %p to tree %p\n", e, t));
130     if (t->root == NULL) {
131         t->root = mknew(node234);
132         t->root->elems[1] = t->root->elems[2] = NULL;
133         t->root->kids[0] = t->root->kids[1] = NULL;
134         t->root->kids[2] = t->root->kids[3] = NULL;
135         t->root->counts[0] = t->root->counts[1] = 0;
136         t->root->counts[2] = t->root->counts[3] = 0;
137         t->root->parent = NULL;
138         t->root->elems[0] = e;
139         LOG(("  created root %p\n", t->root));
140         return orig_e;
141     }
142
143     np = &t->root;
144     while (*np) {
145         int childnum;
146         n = *np;
147         LOG(("  node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
148              n,
149              n->kids[0], n->counts[0], n->elems[0],
150              n->kids[1], n->counts[1], n->elems[1],
151              n->kids[2], n->counts[2], n->elems[2],
152              n->kids[3], n->counts[3]));
153         if (index >= 0) {
154             if (!n->kids[0]) {
155                 /*
156                  * Leaf node. We want to insert at kid position
157                  * equal to the index:
158                  * 
159                  *   0 A 1 B 2 C 3
160                  */
161                 childnum = index;
162             } else {
163                 /*
164                  * Internal node. We always descend through it (add
165                  * always starts at the bottom, never in the
166                  * middle).
167                  */
168                 do {                   /* this is a do ... while (0) to allow `break' */
169                     if (index <= n->counts[0]) {
170                         childnum = 0;
171                         break;
172                     }
173                     index -= n->counts[0] + 1;
174                     if (index <= n->counts[1]) {
175                         childnum = 1;
176                         break;
177                     }
178                     index -= n->counts[1] + 1;
179                     if (index <= n->counts[2]) {
180                         childnum = 2;
181                         break;
182                     }
183                     index -= n->counts[2] + 1;
184                     if (index <= n->counts[3]) {
185                         childnum = 3;
186                         break;
187                     }
188                     return NULL;       /* error: index out of range */
189                 } while (0);
190             }
191         } else {
192             if ((c = t->cmp(e, n->elems[0])) < 0)
193                 childnum = 0;
194             else if (c == 0)
195                 return n->elems[0];    /* already exists */
196             else if (n->elems[1] == NULL
197                      || (c = t->cmp(e, n->elems[1])) < 0) childnum = 1;
198             else if (c == 0)
199                 return n->elems[1];    /* already exists */
200             else if (n->elems[2] == NULL
201                      || (c = t->cmp(e, n->elems[2])) < 0) childnum = 2;
202             else if (c == 0)
203                 return n->elems[2];    /* already exists */
204             else
205                 childnum = 3;
206         }
207         np = &n->kids[childnum];
208         LOG(("  moving to child %d (%p)\n", childnum, *np));
209     }
210
211     /*
212      * We need to insert the new element in n at position np.
213      */
214     left = NULL;
215     lcount = 0;
216     right = NULL;
217     rcount = 0;
218     while (n) {
219         LOG(("  at %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
220              n,
221              n->kids[0], n->counts[0], n->elems[0],
222              n->kids[1], n->counts[1], n->elems[1],
223              n->kids[2], n->counts[2], n->elems[2],
224              n->kids[3], n->counts[3]));
225         LOG(("  need to insert %p/%d [%p] %p/%d at position %d\n",
226              left, lcount, e, right, rcount, np - n->kids));
227         if (n->elems[1] == NULL) {
228             /*
229              * Insert in a 2-node; simple.
230              */
231             if (np == &n->kids[0]) {
232                 LOG(("  inserting on left of 2-node\n"));
233                 n->kids[2] = n->kids[1];
234                 n->counts[2] = n->counts[1];
235                 n->elems[1] = n->elems[0];
236                 n->kids[1] = right;
237                 n->counts[1] = rcount;
238                 n->elems[0] = e;
239                 n->kids[0] = left;
240                 n->counts[0] = lcount;
241             } else {                   /* np == &n->kids[1] */
242                 LOG(("  inserting on right of 2-node\n"));
243                 n->kids[2] = right;
244                 n->counts[2] = rcount;
245                 n->elems[1] = e;
246                 n->kids[1] = left;
247                 n->counts[1] = lcount;
248             }
249             if (n->kids[0])
250                 n->kids[0]->parent = n;
251             if (n->kids[1])
252                 n->kids[1]->parent = n;
253             if (n->kids[2])
254                 n->kids[2]->parent = n;
255             LOG(("  done\n"));
256             break;
257         } else if (n->elems[2] == NULL) {
258             /*
259              * Insert in a 3-node; simple.
260              */
261             if (np == &n->kids[0]) {
262                 LOG(("  inserting on left of 3-node\n"));
263                 n->kids[3] = n->kids[2];
264                 n->counts[3] = n->counts[2];
265                 n->elems[2] = n->elems[1];
266                 n->kids[2] = n->kids[1];
267                 n->counts[2] = n->counts[1];
268                 n->elems[1] = n->elems[0];
269                 n->kids[1] = right;
270                 n->counts[1] = rcount;
271                 n->elems[0] = e;
272                 n->kids[0] = left;
273                 n->counts[0] = lcount;
274             } else if (np == &n->kids[1]) {
275                 LOG(("  inserting in middle of 3-node\n"));
276                 n->kids[3] = n->kids[2];
277                 n->counts[3] = n->counts[2];
278                 n->elems[2] = n->elems[1];
279                 n->kids[2] = right;
280                 n->counts[2] = rcount;
281                 n->elems[1] = e;
282                 n->kids[1] = left;
283                 n->counts[1] = lcount;
284             } else {                   /* np == &n->kids[2] */
285                 LOG(("  inserting on right of 3-node\n"));
286                 n->kids[3] = right;
287                 n->counts[3] = rcount;
288                 n->elems[2] = e;
289                 n->kids[2] = left;
290                 n->counts[2] = lcount;
291             }
292             if (n->kids[0])
293                 n->kids[0]->parent = n;
294             if (n->kids[1])
295                 n->kids[1]->parent = n;
296             if (n->kids[2])
297                 n->kids[2]->parent = n;
298             if (n->kids[3])
299                 n->kids[3]->parent = n;
300             LOG(("  done\n"));
301             break;
302         } else {
303             node234 *m = mknew(node234);
304             m->parent = n->parent;
305             LOG(("  splitting a 4-node; created new node %p\n", m));
306             /*
307              * Insert in a 4-node; split into a 2-node and a
308              * 3-node, and move focus up a level.
309              * 
310              * I don't think it matters which way round we put the
311              * 2 and the 3. For simplicity, we'll put the 3 first
312              * always.
313              */
314             if (np == &n->kids[0]) {
315                 m->kids[0] = left;
316                 m->counts[0] = lcount;
317                 m->elems[0] = e;
318                 m->kids[1] = right;
319                 m->counts[1] = rcount;
320                 m->elems[1] = n->elems[0];
321                 m->kids[2] = n->kids[1];
322                 m->counts[2] = n->counts[1];
323                 e = n->elems[1];
324                 n->kids[0] = n->kids[2];
325                 n->counts[0] = n->counts[2];
326                 n->elems[0] = n->elems[2];
327                 n->kids[1] = n->kids[3];
328                 n->counts[1] = n->counts[3];
329             } else if (np == &n->kids[1]) {
330                 m->kids[0] = n->kids[0];
331                 m->counts[0] = n->counts[0];
332                 m->elems[0] = n->elems[0];
333                 m->kids[1] = left;
334                 m->counts[1] = lcount;
335                 m->elems[1] = e;
336                 m->kids[2] = right;
337                 m->counts[2] = rcount;
338                 e = n->elems[1];
339                 n->kids[0] = n->kids[2];
340                 n->counts[0] = n->counts[2];
341                 n->elems[0] = n->elems[2];
342                 n->kids[1] = n->kids[3];
343                 n->counts[1] = n->counts[3];
344             } else if (np == &n->kids[2]) {
345                 m->kids[0] = n->kids[0];
346                 m->counts[0] = n->counts[0];
347                 m->elems[0] = n->elems[0];
348                 m->kids[1] = n->kids[1];
349                 m->counts[1] = n->counts[1];
350                 m->elems[1] = n->elems[1];
351                 m->kids[2] = left;
352                 m->counts[2] = lcount;
353                 /* e = e; */
354                 n->kids[0] = right;
355                 n->counts[0] = rcount;
356                 n->elems[0] = n->elems[2];
357                 n->kids[1] = n->kids[3];
358                 n->counts[1] = n->counts[3];
359             } else {                   /* np == &n->kids[3] */
360                 m->kids[0] = n->kids[0];
361                 m->counts[0] = n->counts[0];
362                 m->elems[0] = n->elems[0];
363                 m->kids[1] = n->kids[1];
364                 m->counts[1] = n->counts[1];
365                 m->elems[1] = n->elems[1];
366                 m->kids[2] = n->kids[2];
367                 m->counts[2] = n->counts[2];
368                 n->kids[0] = left;
369                 n->counts[0] = lcount;
370                 n->elems[0] = e;
371                 n->kids[1] = right;
372                 n->counts[1] = rcount;
373                 e = n->elems[2];
374             }
375             m->kids[3] = n->kids[3] = n->kids[2] = NULL;
376             m->counts[3] = n->counts[3] = n->counts[2] = 0;
377             m->elems[2] = n->elems[2] = n->elems[1] = NULL;
378             if (m->kids[0])
379                 m->kids[0]->parent = m;
380             if (m->kids[1])
381                 m->kids[1]->parent = m;
382             if (m->kids[2])
383                 m->kids[2]->parent = m;
384             if (n->kids[0])
385                 n->kids[0]->parent = n;
386             if (n->kids[1])
387                 n->kids[1]->parent = n;
388             LOG(("  left (%p): %p/%d [%p] %p/%d [%p] %p/%d\n", m,
389                  m->kids[0], m->counts[0], m->elems[0],
390                  m->kids[1], m->counts[1], m->elems[1],
391                  m->kids[2], m->counts[2]));
392             LOG(("  right (%p): %p/%d [%p] %p/%d\n", n,
393                  n->kids[0], n->counts[0], n->elems[0],
394                  n->kids[1], n->counts[1]));
395             left = m;
396             lcount = countnode234(left);
397             right = n;
398             rcount = countnode234(right);
399         }
400         if (n->parent)
401             np = (n->parent->kids[0] == n ? &n->parent->kids[0] :
402                   n->parent->kids[1] == n ? &n->parent->kids[1] :
403                   n->parent->kids[2] == n ? &n->parent->kids[2] :
404                   &n->parent->kids[3]);
405         n = n->parent;
406     }
407
408     /*
409      * If we've come out of here by `break', n will still be
410      * non-NULL and all we need to do is go back up the tree
411      * updating counts. If we've come here because n is NULL, we
412      * need to create a new root for the tree because the old one
413      * has just split into two. */
414     if (n) {
415         while (n->parent) {
416             int count = countnode234(n);
417             int childnum;
418             childnum = (n->parent->kids[0] == n ? 0 :
419                         n->parent->kids[1] == n ? 1 :
420                         n->parent->kids[2] == n ? 2 : 3);
421             n->parent->counts[childnum] = count;
422             n = n->parent;
423         }
424     } else {
425         LOG(("  root is overloaded, split into two\n"));
426         t->root = mknew(node234);
427         t->root->kids[0] = left;
428         t->root->counts[0] = lcount;
429         t->root->elems[0] = e;
430         t->root->kids[1] = right;
431         t->root->counts[1] = rcount;
432         t->root->elems[1] = NULL;
433         t->root->kids[2] = NULL;
434         t->root->counts[2] = 0;
435         t->root->elems[2] = NULL;
436         t->root->kids[3] = NULL;
437         t->root->counts[3] = 0;
438         t->root->parent = NULL;
439         if (t->root->kids[0])
440             t->root->kids[0]->parent = t->root;
441         if (t->root->kids[1])
442             t->root->kids[1]->parent = t->root;
443         LOG(("  new root is %p/%d [%p] %p/%d\n",
444              t->root->kids[0], t->root->counts[0],
445              t->root->elems[0], t->root->kids[1], t->root->counts[1]));
446     }
447
448     return orig_e;
449 }
450
451 void *add234(tree234 * t, void *e)
452 {
453     if (!t->cmp)                       /* tree is unsorted */
454         return NULL;
455
456     return add234_internal(t, e, -1);
457 }
458 void *addpos234(tree234 * t, void *e, int index)
459 {
460     if (index < 0 ||                   /* index out of range */
461         t->cmp)                        /* tree is sorted */
462         return NULL;                   /* return failure */
463
464     return add234_internal(t, e, index);        /* this checks the upper bound */
465 }
466
467 /*
468  * Look up the element at a given numeric index in a 2-3-4 tree.
469  * Returns NULL if the index is out of range.
470  */
471 void *index234(tree234 * t, int index)
472 {
473     node234 *n;
474
475     if (!t->root)
476         return NULL;                   /* tree is empty */
477
478     if (index < 0 || index >= countnode234(t->root))
479         return NULL;                   /* out of range */
480
481     n = t->root;
482
483     while (n) {
484         if (index < n->counts[0])
485             n = n->kids[0];
486         else if (index -= n->counts[0] + 1, index < 0)
487             return n->elems[0];
488         else if (index < n->counts[1])
489             n = n->kids[1];
490         else if (index -= n->counts[1] + 1, index < 0)
491             return n->elems[1];
492         else if (index < n->counts[2])
493             n = n->kids[2];
494         else if (index -= n->counts[2] + 1, index < 0)
495             return n->elems[2];
496         else
497             n = n->kids[3];
498     }
499
500     /* We shouldn't ever get here. I wonder how we did. */
501     return NULL;
502 }
503
504 /*
505  * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
506  * found. e is always passed as the first argument to cmp, so cmp
507  * can be an asymmetric function if desired. cmp can also be passed
508  * as NULL, in which case the compare function from the tree proper
509  * will be used.
510  */
511 void *findrelpos234(tree234 * t, void *e, cmpfn234 cmp,
512                     int relation, int *index)
513 {
514     node234 *n;
515     void *ret;
516     int c;
517     int idx, ecount, kcount, cmpret;
518
519     if (t->root == NULL)
520         return NULL;
521
522     if (cmp == NULL)
523         cmp = t->cmp;
524
525     n = t->root;
526     /*
527      * Attempt to find the element itself.
528      */
529     idx = 0;
530     ecount = -1;
531     /*
532      * Prepare a fake `cmp' result if e is NULL.
533      */
534     cmpret = 0;
535     if (e == NULL) {
536         assert(relation == REL234_LT || relation == REL234_GT);
537         if (relation == REL234_LT)
538             cmpret = +1;               /* e is a max: always greater */
539         else if (relation == REL234_GT)
540             cmpret = -1;               /* e is a min: always smaller */
541     }
542     while (1) {
543         for (kcount = 0; kcount < 4; kcount++) {
544             if (kcount >= 3 || n->elems[kcount] == NULL ||
545                 (c = cmpret ? cmpret : cmp(e, n->elems[kcount])) < 0) {
546                 break;
547             }
548             if (n->kids[kcount])
549                 idx += n->counts[kcount];
550             if (c == 0) {
551                 ecount = kcount;
552                 break;
553             }
554             idx++;
555         }
556         if (ecount >= 0)
557             break;
558         if (n->kids[kcount])
559             n = n->kids[kcount];
560         else
561             break;
562     }
563
564     if (ecount >= 0) {
565         /*
566          * We have found the element we're looking for. It's
567          * n->elems[ecount], at tree index idx. If our search
568          * relation is EQ, LE or GE we can now go home.
569          */
570         if (relation != REL234_LT && relation != REL234_GT) {
571             if (index)
572                 *index = idx;
573             return n->elems[ecount];
574         }
575
576         /*
577          * Otherwise, we'll do an indexed lookup for the previous
578          * or next element. (It would be perfectly possible to
579          * implement these search types in a non-counted tree by
580          * going back up from where we are, but far more fiddly.)
581          */
582         if (relation == REL234_LT)
583             idx--;
584         else
585             idx++;
586     } else {
587         /*
588          * We've found our way to the bottom of the tree and we
589          * know where we would insert this node if we wanted to:
590          * we'd put it in in place of the (empty) subtree
591          * n->kids[kcount], and it would have index idx
592          * 
593          * But the actual element isn't there. So if our search
594          * relation is EQ, we're doomed.
595          */
596         if (relation == REL234_EQ)
597             return NULL;
598
599         /*
600          * Otherwise, we must do an index lookup for index idx-1
601          * (if we're going left - LE or LT) or index idx (if we're
602          * going right - GE or GT).
603          */
604         if (relation == REL234_LT || relation == REL234_LE) {
605             idx--;
606         }
607     }
608
609     /*
610      * We know the index of the element we want; just call index234
611      * to do the rest. This will return NULL if the index is out of
612      * bounds, which is exactly what we want.
613      */
614     ret = index234(t, idx);
615     if (ret && index)
616         *index = idx;
617     return ret;
618 }
619 void *find234(tree234 * t, void *e, cmpfn234 cmp)
620 {
621     return findrelpos234(t, e, cmp, REL234_EQ, NULL);
622 }
623 void *findrel234(tree234 * t, void *e, cmpfn234 cmp, int relation)
624 {
625     return findrelpos234(t, e, cmp, relation, NULL);
626 }
627 void *findpos234(tree234 * t, void *e, cmpfn234 cmp, int *index)
628 {
629     return findrelpos234(t, e, cmp, REL234_EQ, index);
630 }
631
632 /*
633  * Delete an element e in a 2-3-4 tree. Does not free the element,
634  * merely removes all links to it from the tree nodes.
635  */
636 static void *delpos234_internal(tree234 * t, int index)
637 {
638     node234 *n;
639     void *retval;
640     int ei = -1;
641
642     retval = 0;
643
644     n = t->root;
645     LOG(("deleting item %d from tree %p\n", index, t));
646     while (1) {
647         while (n) {
648             int ki;
649             node234 *sub;
650
651             LOG(
652                 ("  node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d index=%d\n",
653                  n, n->kids[0], n->counts[0], n->elems[0], n->kids[1],
654                  n->counts[1], n->elems[1], n->kids[2], n->counts[2],
655                  n->elems[2], n->kids[3], n->counts[3], index));
656             if (index < n->counts[0]) {
657                 ki = 0;
658             } else if (index -= n->counts[0] + 1, index < 0) {
659                 ei = 0;
660                 break;
661             } else if (index < n->counts[1]) {
662                 ki = 1;
663             } else if (index -= n->counts[1] + 1, index < 0) {
664                 ei = 1;
665                 break;
666             } else if (index < n->counts[2]) {
667                 ki = 2;
668             } else if (index -= n->counts[2] + 1, index < 0) {
669                 ei = 2;
670                 break;
671             } else {
672                 ki = 3;
673             }
674             /*
675              * Recurse down to subtree ki. If it has only one element,
676              * we have to do some transformation to start with.
677              */
678             LOG(("  moving to subtree %d\n", ki));
679             sub = n->kids[ki];
680             if (!sub->elems[1]) {
681                 LOG(("  subtree has only one element!\n", ki));
682                 if (ki > 0 && n->kids[ki - 1]->elems[1]) {
683                     /*
684                      * Case 3a, left-handed variant. Child ki has
685                      * only one element, but child ki-1 has two or
686                      * more. So we need to move a subtree from ki-1
687                      * to ki.
688                      * 
689                      *                . C .                     . B .
690                      *               /     \     ->            /     \
691                      * [more] a A b B c   d D e      [more] a A b   c C d D e
692                      */
693                     node234 *sib = n->kids[ki - 1];
694                     int lastelem = (sib->elems[2] ? 2 :
695                                     sib->elems[1] ? 1 : 0);
696                     sub->kids[2] = sub->kids[1];
697                     sub->counts[2] = sub->counts[1];
698                     sub->elems[1] = sub->elems[0];
699                     sub->kids[1] = sub->kids[0];
700                     sub->counts[1] = sub->counts[0];
701                     sub->elems[0] = n->elems[ki - 1];
702                     sub->kids[0] = sib->kids[lastelem + 1];
703                     sub->counts[0] = sib->counts[lastelem + 1];
704                     if (sub->kids[0])
705                         sub->kids[0]->parent = sub;
706                     n->elems[ki - 1] = sib->elems[lastelem];
707                     sib->kids[lastelem + 1] = NULL;
708                     sib->counts[lastelem + 1] = 0;
709                     sib->elems[lastelem] = NULL;
710                     n->counts[ki] = countnode234(sub);
711                     LOG(("  case 3a left\n"));
712                     LOG(
713                         ("  index and left subtree count before adjustment: %d, %d\n",
714                          index, n->counts[ki - 1]));
715                     index += n->counts[ki - 1];
716                     n->counts[ki - 1] = countnode234(sib);
717                     index -= n->counts[ki - 1];
718                     LOG(
719                         ("  index and left subtree count after adjustment: %d, %d\n",
720                          index, n->counts[ki - 1]));
721                 } else if (ki < 3 && n->kids[ki + 1]
722                            && n->kids[ki + 1]->elems[1]) {
723                     /*
724                      * Case 3a, right-handed variant. ki has only
725                      * one element but ki+1 has two or more. Move a
726                      * subtree from ki+1 to ki.
727                      * 
728                      *      . B .                             . C .
729                      *     /     \                ->         /     \
730                      *  a A b   c C d D e [more]      a A b B c   d D e [more]
731                      */
732                     node234 *sib = n->kids[ki + 1];
733                     int j;
734                     sub->elems[1] = n->elems[ki];
735                     sub->kids[2] = sib->kids[0];
736                     sub->counts[2] = sib->counts[0];
737                     if (sub->kids[2])
738                         sub->kids[2]->parent = sub;
739                     n->elems[ki] = sib->elems[0];
740                     sib->kids[0] = sib->kids[1];
741                     sib->counts[0] = sib->counts[1];
742                     for (j = 0; j < 2 && sib->elems[j + 1]; j++) {
743                         sib->kids[j + 1] = sib->kids[j + 2];
744                         sib->counts[j + 1] = sib->counts[j + 2];
745                         sib->elems[j] = sib->elems[j + 1];
746                     }
747                     sib->kids[j + 1] = NULL;
748                     sib->counts[j + 1] = 0;
749                     sib->elems[j] = NULL;
750                     n->counts[ki] = countnode234(sub);
751                     n->counts[ki + 1] = countnode234(sib);
752                     LOG(("  case 3a right\n"));
753                 } else {
754                     /*
755                      * Case 3b. ki has only one element, and has no
756                      * neighbour with more than one. So pick a
757                      * neighbour and merge it with ki, taking an
758                      * element down from n to go in the middle.
759                      *
760                      *      . B .                .
761                      *     /     \     ->        |
762                      *  a A b   c C d      a A b B c C d
763                      * 
764                      * (Since at all points we have avoided
765                      * descending to a node with only one element,
766                      * we can be sure that n is not reduced to
767                      * nothingness by this move, _unless_ it was
768                      * the very first node, ie the root of the
769                      * tree. In that case we remove the now-empty
770                      * root and replace it with its single large
771                      * child as shown.)
772                      */
773                     node234 *sib;
774                     int j;
775
776                     if (ki > 0) {
777                         ki--;
778                         index += n->counts[ki] + 1;
779                     }
780                     sib = n->kids[ki];
781                     sub = n->kids[ki + 1];
782
783                     sub->kids[3] = sub->kids[1];
784                     sub->counts[3] = sub->counts[1];
785                     sub->elems[2] = sub->elems[0];
786                     sub->kids[2] = sub->kids[0];
787                     sub->counts[2] = sub->counts[0];
788                     sub->elems[1] = n->elems[ki];
789                     sub->kids[1] = sib->kids[1];
790                     sub->counts[1] = sib->counts[1];
791                     if (sub->kids[1])
792                         sub->kids[1]->parent = sub;
793                     sub->elems[0] = sib->elems[0];
794                     sub->kids[0] = sib->kids[0];
795                     sub->counts[0] = sib->counts[0];
796                     if (sub->kids[0])
797                         sub->kids[0]->parent = sub;
798
799                     n->counts[ki + 1] = countnode234(sub);
800
801                     sfree(sib);
802
803                     /*
804                      * That's built the big node in sub. Now we
805                      * need to remove the reference to sib in n.
806                      */
807                     for (j = ki; j < 3 && n->kids[j + 1]; j++) {
808                         n->kids[j] = n->kids[j + 1];
809                         n->counts[j] = n->counts[j + 1];
810                         n->elems[j] = j < 2 ? n->elems[j + 1] : NULL;
811                     }
812                     n->kids[j] = NULL;
813                     n->counts[j] = 0;
814                     if (j < 3)
815                         n->elems[j] = NULL;
816                     LOG(("  case 3b ki=%d\n", ki));
817
818                     if (!n->elems[0]) {
819                         /*
820                          * The root is empty and needs to be
821                          * removed.
822                          */
823                         LOG(("  shifting root!\n"));
824                         t->root = sub;
825                         sub->parent = NULL;
826                         sfree(n);
827                     }
828                 }
829             }
830             n = sub;
831         }
832         if (!retval)
833             retval = n->elems[ei];
834
835         if (ei == -1)
836             return NULL;               /* although this shouldn't happen */
837
838         /*
839          * Treat special case: this is the one remaining item in
840          * the tree. n is the tree root (no parent), has one
841          * element (no elems[1]), and has no kids (no kids[0]).
842          */
843         if (!n->parent && !n->elems[1] && !n->kids[0]) {
844             LOG(("  removed last element in tree\n"));
845             sfree(n);
846             t->root = NULL;
847             return retval;
848         }
849
850         /*
851          * Now we have the element we want, as n->elems[ei], and we
852          * have also arranged for that element not to be the only
853          * one in its node. So...
854          */
855
856         if (!n->kids[0] && n->elems[1]) {
857             /*
858              * Case 1. n is a leaf node with more than one element,
859              * so it's _really easy_. Just delete the thing and
860              * we're done.
861              */
862             int i;
863             LOG(("  case 1\n"));
864             for (i = ei; i < 2 && n->elems[i + 1]; i++)
865                 n->elems[i] = n->elems[i + 1];
866             n->elems[i] = NULL;
867             /*
868              * Having done that to the leaf node, we now go back up
869              * the tree fixing the counts.
870              */
871             while (n->parent) {
872                 int childnum;
873                 childnum = (n->parent->kids[0] == n ? 0 :
874                             n->parent->kids[1] == n ? 1 :
875                             n->parent->kids[2] == n ? 2 : 3);
876                 n->parent->counts[childnum]--;
877                 n = n->parent;
878             }
879             return retval;             /* finished! */
880         } else if (n->kids[ei]->elems[1]) {
881             /*
882              * Case 2a. n is an internal node, and the root of the
883              * subtree to the left of e has more than one element.
884              * So find the predecessor p to e (ie the largest node
885              * in that subtree), place it where e currently is, and
886              * then start the deletion process over again on the
887              * subtree with p as target.
888              */
889             node234 *m = n->kids[ei];
890             void *target;
891             LOG(("  case 2a\n"));
892             while (m->kids[0]) {
893                 m = (m->kids[3] ? m->kids[3] :
894                      m->kids[2] ? m->kids[2] :
895                      m->kids[1] ? m->kids[1] : m->kids[0]);
896             }
897             target = (m->elems[2] ? m->elems[2] :
898                       m->elems[1] ? m->elems[1] : m->elems[0]);
899             n->elems[ei] = target;
900             index = n->counts[ei] - 1;
901             n = n->kids[ei];
902         } else if (n->kids[ei + 1]->elems[1]) {
903             /*
904              * Case 2b, symmetric to 2a but s/left/right/ and
905              * s/predecessor/successor/. (And s/largest/smallest/).
906              */
907             node234 *m = n->kids[ei + 1];
908             void *target;
909             LOG(("  case 2b\n"));
910             while (m->kids[0]) {
911                 m = m->kids[0];
912             }
913             target = m->elems[0];
914             n->elems[ei] = target;
915             n = n->kids[ei + 1];
916             index = 0;
917         } else {
918             /*
919              * Case 2c. n is an internal node, and the subtrees to
920              * the left and right of e both have only one element.
921              * So combine the two subnodes into a single big node
922              * with their own elements on the left and right and e
923              * in the middle, then restart the deletion process on
924              * that subtree, with e still as target.
925              */
926             node234 *a = n->kids[ei], *b = n->kids[ei + 1];
927             int j;
928
929             LOG(("  case 2c\n"));
930             a->elems[1] = n->elems[ei];
931             a->kids[2] = b->kids[0];
932             a->counts[2] = b->counts[0];
933             if (a->kids[2])
934                 a->kids[2]->parent = a;
935             a->elems[2] = b->elems[0];
936             a->kids[3] = b->kids[1];
937             a->counts[3] = b->counts[1];
938             if (a->kids[3])
939                 a->kids[3]->parent = a;
940             sfree(b);
941             n->counts[ei] = countnode234(a);
942             /*
943              * That's built the big node in a, and destroyed b. Now
944              * remove the reference to b (and e) in n.
945              */
946             for (j = ei; j < 2 && n->elems[j + 1]; j++) {
947                 n->elems[j] = n->elems[j + 1];
948                 n->kids[j + 1] = n->kids[j + 2];
949                 n->counts[j + 1] = n->counts[j + 2];
950             }
951             n->elems[j] = NULL;
952             n->kids[j + 1] = NULL;
953             n->counts[j + 1] = 0;
954             /*
955              * It's possible, in this case, that we've just removed
956              * the only element in the root of the tree. If so,
957              * shift the root.
958              */
959             if (n->elems[0] == NULL) {
960                 LOG(("  shifting root!\n"));
961                 t->root = a;
962                 a->parent = NULL;
963                 sfree(n);
964             }
965             /*
966              * Now go round the deletion process again, with n
967              * pointing at the new big node and e still the same.
968              */
969             n = a;
970             index = a->counts[0] + a->counts[1] + 1;
971         }
972     }
973 }
974 void *delpos234(tree234 * t, int index)
975 {
976     if (index < 0 || index >= countnode234(t->root))
977         return NULL;
978     return delpos234_internal(t, index);
979 }
980 void *del234(tree234 * t, void *e)
981 {
982     int index;
983     if (!findrelpos234(t, e, NULL, REL234_EQ, &index))
984         return NULL;                   /* it wasn't in there anyway */
985     return delpos234_internal(t, index);        /* it's there; delete it. */
986 }
987
988 #ifdef TEST
989
990 /*
991  * Test code for the 2-3-4 tree. This code maintains an alternative
992  * representation of the data in the tree, in an array (using the
993  * obvious and slow insert and delete functions). After each tree
994  * operation, the verify() function is called, which ensures all
995  * the tree properties are preserved:
996  *  - node->child->parent always equals node
997  *  - tree->root->parent always equals NULL
998  *  - number of kids == 0 or number of elements + 1;
999  *  - tree has the same depth everywhere
1000  *  - every node has at least one element
1001  *  - subtree element counts are accurate
1002  *  - any NULL kid pointer is accompanied by a zero count
1003  *  - in a sorted tree: ordering property between elements of a
1004  *    node and elements of its children is preserved
1005  * and also ensures the list represented by the tree is the same
1006  * list it should be. (This last check also doubly verifies the
1007  * ordering properties, because the `same list it should be' is by
1008  * definition correctly ordered. It also ensures all nodes are
1009  * distinct, because the enum functions would get caught in a loop
1010  * if not.)
1011  */
1012
1013 #include <stdarg.h>
1014
1015 #define srealloc realloc
1016
1017 /*
1018  * Error reporting function.
1019  */
1020 void error(char *fmt, ...)
1021 {
1022     va_list ap;
1023     printf("ERROR: ");
1024     va_start(ap, fmt);
1025     vfprintf(stdout, fmt, ap);
1026     va_end(ap);
1027     printf("\n");
1028 }
1029
1030 /* The array representation of the data. */
1031 void **array;
1032 int arraylen, arraysize;
1033 cmpfn234 cmp;
1034
1035 /* The tree representation of the same data. */
1036 tree234 *tree;
1037
1038 typedef struct {
1039     int treedepth;
1040     int elemcount;
1041 } chkctx;
1042
1043 int chknode(chkctx * ctx, int level, node234 * node,
1044             void *lowbound, void *highbound)
1045 {
1046     int nkids, nelems;
1047     int i;
1048     int count;
1049
1050     /* Count the non-NULL kids. */
1051     for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
1052     /* Ensure no kids beyond the first NULL are non-NULL. */
1053     for (i = nkids; i < 4; i++)
1054         if (node->kids[i]) {
1055             error("node %p: nkids=%d but kids[%d] non-NULL",
1056                   node, nkids, i);
1057         } else if (node->counts[i]) {
1058             error("node %p: kids[%d] NULL but count[%d]=%d nonzero",
1059                   node, i, i, node->counts[i]);
1060         }
1061
1062     /* Count the non-NULL elements. */
1063     for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
1064     /* Ensure no elements beyond the first NULL are non-NULL. */
1065     for (i = nelems; i < 3; i++)
1066         if (node->elems[i]) {
1067             error("node %p: nelems=%d but elems[%d] non-NULL",
1068                   node, nelems, i);
1069         }
1070
1071     if (nkids == 0) {
1072         /*
1073          * If nkids==0, this is a leaf node; verify that the tree
1074          * depth is the same everywhere.
1075          */
1076         if (ctx->treedepth < 0)
1077             ctx->treedepth = level;    /* we didn't know the depth yet */
1078         else if (ctx->treedepth != level)
1079             error("node %p: leaf at depth %d, previously seen depth %d",
1080                   node, level, ctx->treedepth);
1081     } else {
1082         /*
1083          * If nkids != 0, then it should be nelems+1, unless nelems
1084          * is 0 in which case nkids should also be 0 (and so we
1085          * shouldn't be in this condition at all).
1086          */
1087         int shouldkids = (nelems ? nelems + 1 : 0);
1088         if (nkids != shouldkids) {
1089             error("node %p: %d elems should mean %d kids but has %d",
1090                   node, nelems, shouldkids, nkids);
1091         }
1092     }
1093
1094     /*
1095      * nelems should be at least 1.
1096      */
1097     if (nelems == 0) {
1098         error("node %p: no elems", node, nkids);
1099     }
1100
1101     /*
1102      * Add nelems to the running element count of the whole tree.
1103      */
1104     ctx->elemcount += nelems;
1105
1106     /*
1107      * Check ordering property: all elements should be strictly >
1108      * lowbound, strictly < highbound, and strictly < each other in
1109      * sequence. (lowbound and highbound are NULL at edges of tree
1110      * - both NULL at root node - and NULL is considered to be <
1111      * everything and > everything. IYSWIM.)
1112      */
1113     if (cmp) {
1114         for (i = -1; i < nelems; i++) {
1115             void *lower = (i == -1 ? lowbound : node->elems[i]);
1116             void *higher =
1117                 (i + 1 == nelems ? highbound : node->elems[i + 1]);
1118             if (lower && higher && cmp(lower, higher) >= 0) {
1119                 error("node %p: kid comparison [%d=%s,%d=%s] failed",
1120                       node, i, lower, i + 1, higher);
1121             }
1122         }
1123     }
1124
1125     /*
1126      * Check parent pointers: all non-NULL kids should have a
1127      * parent pointer coming back to this node.
1128      */
1129     for (i = 0; i < nkids; i++)
1130         if (node->kids[i]->parent != node) {
1131             error("node %p kid %d: parent ptr is %p not %p",
1132                   node, i, node->kids[i]->parent, node);
1133         }
1134
1135
1136     /*
1137      * Now (finally!) recurse into subtrees.
1138      */
1139     count = nelems;
1140
1141     for (i = 0; i < nkids; i++) {
1142         void *lower = (i == 0 ? lowbound : node->elems[i - 1]);
1143         void *higher = (i >= nelems ? highbound : node->elems[i]);
1144         int subcount =
1145             chknode(ctx, level + 1, node->kids[i], lower, higher);
1146         if (node->counts[i] != subcount) {
1147             error("node %p kid %d: count says %d, subtree really has %d",
1148                   node, i, node->counts[i], subcount);
1149         }
1150         count += subcount;
1151     }
1152
1153     return count;
1154 }
1155
1156 void verify(void)
1157 {
1158     chkctx ctx;
1159     int i;
1160     void *p;
1161
1162     ctx.treedepth = -1;                /* depth unknown yet */
1163     ctx.elemcount = 0;                 /* no elements seen yet */
1164     /*
1165      * Verify validity of tree properties.
1166      */
1167     if (tree->root) {
1168         if (tree->root->parent != NULL)
1169             error("root->parent is %p should be null", tree->root->parent);
1170         chknode(&ctx, 0, tree->root, NULL, NULL);
1171     }
1172     printf("tree depth: %d\n", ctx.treedepth);
1173     /*
1174      * Enumerate the tree and ensure it matches up to the array.
1175      */
1176     for (i = 0; NULL != (p = index234(tree, i)); i++) {
1177         if (i >= arraylen)
1178             error("tree contains more than %d elements", arraylen);
1179         if (array[i] != p)
1180             error("enum at position %d: array says %s, tree says %s",
1181                   i, array[i], p);
1182     }
1183     if (ctx.elemcount != i) {
1184         error("tree really contains %d elements, enum gave %d",
1185               ctx.elemcount, i);
1186     }
1187     if (i < arraylen) {
1188         error("enum gave only %d elements, array has %d", i, arraylen);
1189     }
1190     i = count234(tree);
1191     if (ctx.elemcount != i) {
1192         error("tree really contains %d elements, count234 gave %d",
1193               ctx.elemcount, i);
1194     }
1195 }
1196
1197 void internal_addtest(void *elem, int index, void *realret)
1198 {
1199     int i, j;
1200     void *retval;
1201
1202     if (arraysize < arraylen + 1) {
1203         arraysize = arraylen + 1 + 256;
1204         array = (array == NULL ? smalloc(arraysize * sizeof(*array)) :
1205                  srealloc(array, arraysize * sizeof(*array)));
1206     }
1207
1208     i = index;
1209     /* now i points to the first element >= elem */
1210     retval = elem;                     /* expect elem returned (success) */
1211     for (j = arraylen; j > i; j--)
1212         array[j] = array[j - 1];
1213     array[i] = elem;                   /* add elem to array */
1214     arraylen++;
1215
1216     if (realret != retval) {
1217         error("add: retval was %p expected %p", realret, retval);
1218     }
1219
1220     verify();
1221 }
1222
1223 void addtest(void *elem)
1224 {
1225     int i;
1226     void *realret;
1227
1228     realret = add234(tree, elem);
1229
1230     i = 0;
1231     while (i < arraylen && cmp(elem, array[i]) > 0)
1232         i++;
1233     if (i < arraylen && !cmp(elem, array[i])) {
1234         void *retval = array[i];       /* expect that returned not elem */
1235         if (realret != retval) {
1236             error("add: retval was %p expected %p", realret, retval);
1237         }
1238     } else
1239         internal_addtest(elem, i, realret);
1240 }
1241
1242 void addpostest(void *elem, int i)
1243 {
1244     void *realret;
1245
1246     realret = addpos234(tree, elem, i);
1247
1248     internal_addtest(elem, i, realret);
1249 }
1250
1251 void delpostest(int i)
1252 {
1253     int index = i;
1254     void *elem = array[i], *ret;
1255
1256     /* i points to the right element */
1257     while (i < arraylen - 1) {
1258         array[i] = array[i + 1];
1259         i++;
1260     }
1261     arraylen--;                        /* delete elem from array */
1262
1263     if (tree->cmp)
1264         ret = del234(tree, elem);
1265     else
1266         ret = delpos234(tree, index);
1267
1268     if (ret != elem) {
1269         error("del returned %p, expected %p", ret, elem);
1270     }
1271
1272     verify();
1273 }
1274
1275 void deltest(void *elem)
1276 {
1277     int i;
1278
1279     i = 0;
1280     while (i < arraylen && cmp(elem, array[i]) > 0)
1281         i++;
1282     if (i >= arraylen || cmp(elem, array[i]) != 0)
1283         return;                        /* don't do it! */
1284     delpostest(i);
1285 }
1286
1287 /* A sample data set and test utility. Designed for pseudo-randomness,
1288  * and yet repeatability. */
1289
1290 /*
1291  * This random number generator uses the `portable implementation'
1292  * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits;
1293  * change it if not.
1294  */
1295 int randomnumber(unsigned *seed)
1296 {
1297     *seed *= 1103515245;
1298     *seed += 12345;
1299     return ((*seed) / 65536) % 32768;
1300 }
1301
1302 int mycmp(void *av, void *bv)
1303 {
1304     char const *a = (char const *) av;
1305     char const *b = (char const *) bv;
1306     return strcmp(a, b);
1307 }
1308
1309 #define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
1310
1311 char *strings[] = {
1312     "a", "ab", "absque", "coram", "de",
1313     "palam", "clam", "cum", "ex", "e",
1314     "sine", "tenus", "pro", "prae",
1315     "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
1316     "penguin", "blancmange", "pangolin", "whale", "hedgehog",
1317     "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
1318     "murfl", "spoo", "breen", "flarn", "octothorpe",
1319     "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
1320     "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
1321     "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
1322     "wand", "ring", "amulet"
1323 };
1324
1325 #define NSTR lenof(strings)
1326
1327 int findtest(void)
1328 {
1329     const static int rels[] = {
1330         REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT
1331     };
1332     const static char *const relnames[] = {
1333         "EQ", "GE", "LE", "LT", "GT"
1334     };
1335     int i, j, rel, index;
1336     char *p, *ret, *realret, *realret2;
1337     int lo, hi, mid, c;
1338
1339     for (i = 0; i < NSTR; i++) {
1340         p = strings[i];
1341         for (j = 0; j < sizeof(rels) / sizeof(*rels); j++) {
1342             rel = rels[j];
1343
1344             lo = 0;
1345             hi = arraylen - 1;
1346             while (lo <= hi) {
1347                 mid = (lo + hi) / 2;
1348                 c = strcmp(p, array[mid]);
1349                 if (c < 0)
1350                     hi = mid - 1;
1351                 else if (c > 0)
1352                     lo = mid + 1;
1353                 else
1354                     break;
1355             }
1356
1357             if (c == 0) {
1358                 if (rel == REL234_LT)
1359                     ret = (mid > 0 ? array[--mid] : NULL);
1360                 else if (rel == REL234_GT)
1361                     ret = (mid < arraylen - 1 ? array[++mid] : NULL);
1362                 else
1363                     ret = array[mid];
1364             } else {
1365                 assert(lo == hi + 1);
1366                 if (rel == REL234_LT || rel == REL234_LE) {
1367                     mid = hi;
1368                     ret = (hi >= 0 ? array[hi] : NULL);
1369                 } else if (rel == REL234_GT || rel == REL234_GE) {
1370                     mid = lo;
1371                     ret = (lo < arraylen ? array[lo] : NULL);
1372                 } else
1373                     ret = NULL;
1374             }
1375
1376             realret = findrelpos234(tree, p, NULL, rel, &index);
1377             if (realret != ret) {
1378                 error("find(\"%s\",%s) gave %s should be %s",
1379                       p, relnames[j], realret, ret);
1380             }
1381             if (realret && index != mid) {
1382                 error("find(\"%s\",%s) gave %d should be %d",
1383                       p, relnames[j], index, mid);
1384             }
1385             if (realret && rel == REL234_EQ) {
1386                 realret2 = index234(tree, index);
1387                 if (realret2 != realret) {
1388                     error("find(\"%s\",%s) gave %s(%d) but %d -> %s",
1389                           p, relnames[j], realret, index, index, realret2);
1390                 }
1391             }
1392 #if 0
1393             printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j],
1394                    realret, index);
1395 #endif
1396         }
1397     }
1398
1399     realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index);
1400     if (arraylen && (realret != array[0] || index != 0)) {
1401         error("find(NULL,GT) gave %s(%d) should be %s(0)",
1402               realret, index, array[0]);
1403     } else if (!arraylen && (realret != NULL)) {
1404         error("find(NULL,GT) gave %s(%d) should be NULL", realret, index);
1405     }
1406
1407     realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index);
1408     if (arraylen
1409         && (realret != array[arraylen - 1] || index != arraylen - 1)) {
1410         error("find(NULL,LT) gave %s(%d) should be %s(0)", realret, index,
1411               array[arraylen - 1]);
1412     } else if (!arraylen && (realret != NULL)) {
1413         error("find(NULL,LT) gave %s(%d) should be NULL", realret, index);
1414     }
1415 }
1416
1417 int main(void)
1418 {
1419     int in[NSTR];
1420     int i, j, k;
1421     unsigned seed = 0;
1422
1423     for (i = 0; i < NSTR; i++)
1424         in[i] = 0;
1425     array = NULL;
1426     arraylen = arraysize = 0;
1427     tree = newtree234(mycmp);
1428     cmp = mycmp;
1429
1430     verify();
1431     for (i = 0; i < 10000; i++) {
1432         j = randomnumber(&seed);
1433         j %= NSTR;
1434         printf("trial: %d\n", i);
1435         if (in[j]) {
1436             printf("deleting %s (%d)\n", strings[j], j);
1437             deltest(strings[j]);
1438             in[j] = 0;
1439         } else {
1440             printf("adding %s (%d)\n", strings[j], j);
1441             addtest(strings[j]);
1442             in[j] = 1;
1443         }
1444         findtest();
1445     }
1446
1447     while (arraylen > 0) {
1448         j = randomnumber(&seed);
1449         j %= arraylen;
1450         deltest(array[j]);
1451     }
1452
1453     freetree234(tree);
1454
1455     /*
1456      * Now try an unsorted tree. We don't really need to test
1457      * delpos234 because we know del234 is based on it, so it's
1458      * already been tested in the above sorted-tree code; but for
1459      * completeness we'll use it to tear down our unsorted tree
1460      * once we've built it.
1461      */
1462     tree = newtree234(NULL);
1463     cmp = NULL;
1464     verify();
1465     for (i = 0; i < 1000; i++) {
1466         printf("trial: %d\n", i);
1467         j = randomnumber(&seed);
1468         j %= NSTR;
1469         k = randomnumber(&seed);
1470         k %= count234(tree) + 1;
1471         printf("adding string %s at index %d\n", strings[j], k);
1472         addpostest(strings[j], k);
1473     }
1474     while (count234(tree) > 0) {
1475         printf("cleanup: tree size %d\n", count234(tree));
1476         j = randomnumber(&seed);
1477         j %= count234(tree);
1478         printf("deleting string %s from index %d\n", array[j], j);
1479         delpostest(j);
1480     }
1481
1482     return 0;
1483 }
1484
1485 #endif