summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/tree234.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/tree234.c')
-rw-r--r--apps/plugins/puzzles/src/tree234.c782
1 files changed, 14 insertions, 768 deletions
diff --git a/apps/plugins/puzzles/src/tree234.c b/apps/plugins/puzzles/src/tree234.c
index ad8eb047cd..ef2c3ffaf7 100644
--- a/apps/plugins/puzzles/src/tree234.c
+++ b/apps/plugins/puzzles/src/tree234.c
@@ -29,33 +29,25 @@
29#include <stdlib.h> 29#include <stdlib.h>
30#include <assert.h> 30#include <assert.h>
31 31
32#define TREE234_INTERNALS
32#include "tree234.h" 33#include "tree234.h"
33 34
34#include "puzzles.h" /* for smalloc/sfree */ 35#include "puzzles.h" /* for smalloc/sfree */
35 36
36#ifdef TEST 37#ifdef DEBUG_TREE234
37#define LOG(x) (printf x) 38#include <stdarg.h>
38#define smalloc malloc 39static void logprintf(const char *fmt, ...)
39#define srealloc realloc 40{
40#define sfree free 41 va_list ap;
42 va_start(ap, fmt);
43 vprintf(fmt, ap);
44 va_end(ap);
45}
46#define LOG(x) (logprintf x)
41#else 47#else
42#define LOG(x) 48#define LOG(x)
43#endif 49#endif
44 50
45typedef struct node234_Tag node234;
46
47struct tree234_Tag {
48 node234 *root;
49 cmpfn234 cmp;
50};
51
52struct node234_Tag {
53 node234 *parent;
54 node234 *kids[4];
55 int counts[4];
56 void *elems[3];
57};
58
59/* 51/*
60 * Create a 2-3-4 tree. 52 * Create a 2-3-4 tree.
61 */ 53 */
@@ -327,7 +319,7 @@ static void *add234_internal(tree234 *t, void *e, int index) {
327 } 319 }
328 320
329 n = t->root; 321 n = t->root;
330 while (n) { 322 do {
331 LOG((" node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n", 323 LOG((" node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",
332 n, 324 n,
333 n->kids[0], n->counts[0], n->elems[0], 325 n->kids[0], n->counts[0], n->elems[0],
@@ -380,7 +372,7 @@ static void *add234_internal(tree234 *t, void *e, int index) {
380 if (!n->kids[ki]) 372 if (!n->kids[ki])
381 break; 373 break;
382 n = n->kids[ki]; 374 n = n->kids[ki];
383 } 375 } while (n);
384 376
385 add234_insert(NULL, e, NULL, &t->root, n, ki); 377 add234_insert(NULL, e, NULL, &t->root, n, ki);
386 378
@@ -1104,7 +1096,7 @@ static node234 *join234_internal(node234 *left, void *sep,
1104 1096
1105 return root; 1097 return root;
1106} 1098}
1107static int height234(tree234 *t) { 1099int height234(tree234 *t) {
1108 int level = 0; 1100 int level = 0;
1109 node234 *n = t->root; 1101 node234 *n = t->root;
1110 while (n) { 1102 while (n) {
@@ -1452,749 +1444,3 @@ tree234 *copytree234(tree234 *t, copyfn234 copyfn, void *copyfnstate) {
1452 1444
1453 return t2; 1445 return t2;
1454} 1446}
1455
1456#ifdef TEST
1457
1458/*
1459 * Test code for the 2-3-4 tree. This code maintains an alternative
1460 * representation of the data in the tree, in an array (using the
1461 * obvious and slow insert and delete functions). After each tree
1462 * operation, the verify() function is called, which ensures all
1463 * the tree properties are preserved:
1464 * - node->child->parent always equals node
1465 * - tree->root->parent always equals NULL
1466 * - number of kids == 0 or number of elements + 1;
1467 * - tree has the same depth everywhere
1468 * - every node has at least one element
1469 * - subtree element counts are accurate
1470 * - any NULL kid pointer is accompanied by a zero count
1471 * - in a sorted tree: ordering property between elements of a
1472 * node and elements of its children is preserved
1473 * and also ensures the list represented by the tree is the same
1474 * list it should be. (This last check also doubly verifies the
1475 * ordering properties, because the `same list it should be' is by
1476 * definition correctly ordered. It also ensures all nodes are
1477 * distinct, because the enum functions would get caught in a loop
1478 * if not.)
1479 */
1480
1481#include <string.h>
1482#include <stdarg.h>
1483
1484#define srealloc realloc
1485
1486/*
1487 * Error reporting function.
1488 */
1489void error(char *fmt, ...) {
1490 va_list ap;
1491 printf("ERROR: ");
1492 va_start(ap, fmt);
1493 vfprintf(stdout, fmt, ap);
1494 va_end(ap);
1495 printf("\n");
1496}
1497
1498/* The array representation of the data. */
1499void **array;
1500int arraylen, arraysize;
1501cmpfn234 cmp;
1502
1503/* The tree representation of the same data. */
1504tree234 *tree;
1505
1506/*
1507 * Routines to provide a diagnostic printout of a tree. Currently
1508 * relies on every element in the tree being a one-character string
1509 * :-)
1510 */
1511typedef struct {
1512 char **levels;
1513} dispctx;
1514
1515int dispnode(node234 *n, int level, dispctx *ctx) {
1516 if (level == 0) {
1517 int xpos = strlen(ctx->levels[0]);
1518 int len;
1519
1520 if (n->elems[2])
1521 len = sprintf(ctx->levels[0]+xpos, " %s%s%s",
1522 n->elems[0], n->elems[1], n->elems[2]);
1523 else if (n->elems[1])
1524 len = sprintf(ctx->levels[0]+xpos, " %s%s",
1525 n->elems[0], n->elems[1]);
1526 else
1527 len = sprintf(ctx->levels[0]+xpos, " %s",
1528 n->elems[0]);
1529 return xpos + 1 + (len-1) / 2;
1530 } else {
1531 int xpos[4], nkids;
1532 int nodelen, mypos, myleft, x, i;
1533
1534 xpos[0] = dispnode(n->kids[0], level-3, ctx);
1535 xpos[1] = dispnode(n->kids[1], level-3, ctx);
1536 nkids = 2;
1537 if (n->kids[2]) {
1538 xpos[2] = dispnode(n->kids[2], level-3, ctx);
1539 nkids = 3;
1540 }
1541 if (n->kids[3]) {
1542 xpos[3] = dispnode(n->kids[3], level-3, ctx);
1543 nkids = 4;
1544 }
1545
1546 if (nkids == 4)
1547 mypos = (xpos[1] + xpos[2]) / 2;
1548 else if (nkids == 3)
1549 mypos = xpos[1];
1550 else
1551 mypos = (xpos[0] + xpos[1]) / 2;
1552 nodelen = nkids * 2 - 1;
1553 myleft = mypos - ((nodelen-1)/2);
1554 assert(myleft >= xpos[0]);
1555 assert(myleft + nodelen-1 <= xpos[nkids-1]);
1556
1557 x = strlen(ctx->levels[level]);
1558 while (x <= xpos[0] && x < myleft)
1559 ctx->levels[level][x++] = ' ';
1560 while (x < myleft)
1561 ctx->levels[level][x++] = '_';
1562 if (nkids==4)
1563 x += sprintf(ctx->levels[level]+x, ".%s.%s.%s.",
1564 n->elems[0], n->elems[1], n->elems[2]);
1565 else if (nkids==3)
1566 x += sprintf(ctx->levels[level]+x, ".%s.%s.",
1567 n->elems[0], n->elems[1]);
1568 else
1569 x += sprintf(ctx->levels[level]+x, ".%s.",
1570 n->elems[0]);
1571 while (x < xpos[nkids-1])
1572 ctx->levels[level][x++] = '_';
1573 ctx->levels[level][x] = '\0';
1574
1575 x = strlen(ctx->levels[level-1]);
1576 for (i = 0; i < nkids; i++) {
1577 int rpos, pos;
1578 rpos = xpos[i];
1579 if (i > 0 && i < nkids-1)
1580 pos = myleft + 2*i;
1581 else
1582 pos = rpos;
1583 if (rpos < pos)
1584 rpos++;
1585 while (x < pos && x < rpos)
1586 ctx->levels[level-1][x++] = ' ';
1587 if (x == pos)
1588 ctx->levels[level-1][x++] = '|';
1589 while (x < pos || x < rpos)
1590 ctx->levels[level-1][x++] = '_';
1591 if (x == pos)
1592 ctx->levels[level-1][x++] = '|';
1593 }
1594 ctx->levels[level-1][x] = '\0';
1595
1596 x = strlen(ctx->levels[level-2]);
1597 for (i = 0; i < nkids; i++) {
1598 int rpos = xpos[i];
1599
1600 while (x < rpos)
1601 ctx->levels[level-2][x++] = ' ';
1602 ctx->levels[level-2][x++] = '|';
1603 }
1604 ctx->levels[level-2][x] = '\0';
1605
1606 return mypos;
1607 }
1608}
1609
1610void disptree(tree234 *t) {
1611 dispctx ctx;
1612 char *leveldata;
1613 int width = count234(t);
1614 int ht = height234(t) * 3 - 2;
1615 int i;
1616
1617 if (!t->root) {
1618 printf("[empty tree]\n");
1619 }
1620
1621 leveldata = smalloc(ht * (width+2));
1622 ctx.levels = smalloc(ht * sizeof(char *));
1623 for (i = 0; i < ht; i++) {
1624 ctx.levels[i] = leveldata + i * (width+2);
1625 ctx.levels[i][0] = '\0';
1626 }
1627
1628 (void) dispnode(t->root, ht-1, &ctx);
1629
1630 for (i = ht; i-- ;)
1631 printf("%s\n", ctx.levels[i]);
1632
1633 sfree(ctx.levels);
1634 sfree(leveldata);
1635}
1636
1637typedef struct {
1638 int treedepth;
1639 int elemcount;
1640} chkctx;
1641
1642int chknode(chkctx *ctx, int level, node234 *node,
1643 void *lowbound, void *highbound) {
1644 int nkids, nelems;
1645 int i;
1646 int count;
1647
1648 /* Count the non-NULL kids. */
1649 for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
1650 /* Ensure no kids beyond the first NULL are non-NULL. */
1651 for (i = nkids; i < 4; i++)
1652 if (node->kids[i]) {
1653 error("node %p: nkids=%d but kids[%d] non-NULL",
1654 node, nkids, i);
1655 } else if (node->counts[i]) {
1656 error("node %p: kids[%d] NULL but count[%d]=%d nonzero",
1657 node, i, i, node->counts[i]);
1658 }
1659
1660 /* Count the non-NULL elements. */
1661 for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
1662 /* Ensure no elements beyond the first NULL are non-NULL. */
1663 for (i = nelems; i < 3; i++)
1664 if (node->elems[i]) {
1665 error("node %p: nelems=%d but elems[%d] non-NULL",
1666 node, nelems, i);
1667 }
1668
1669 if (nkids == 0) {
1670 /*
1671 * If nkids==0, this is a leaf node; verify that the tree
1672 * depth is the same everywhere.
1673 */
1674 if (ctx->treedepth < 0)
1675 ctx->treedepth = level; /* we didn't know the depth yet */
1676 else if (ctx->treedepth != level)
1677 error("node %p: leaf at depth %d, previously seen depth %d",
1678 node, level, ctx->treedepth);
1679 } else {
1680 /*
1681 * If nkids != 0, then it should be nelems+1, unless nelems
1682 * is 0 in which case nkids should also be 0 (and so we
1683 * shouldn't be in this condition at all).
1684 */
1685 int shouldkids = (nelems ? nelems+1 : 0);
1686 if (nkids != shouldkids) {
1687 error("node %p: %d elems should mean %d kids but has %d",
1688 node, nelems, shouldkids, nkids);
1689 }
1690 }
1691
1692 /*
1693 * nelems should be at least 1.
1694 */
1695 if (nelems == 0) {
1696 error("node %p: no elems", node, nkids);
1697 }
1698
1699 /*
1700 * Add nelems to the running element count of the whole tree.
1701 */
1702 ctx->elemcount += nelems;
1703
1704 /*
1705 * Check ordering property: all elements should be strictly >
1706 * lowbound, strictly < highbound, and strictly < each other in
1707 * sequence. (lowbound and highbound are NULL at edges of tree
1708 * - both NULL at root node - and NULL is considered to be <
1709 * everything and > everything. IYSWIM.)
1710 */
1711 if (cmp) {
1712 for (i = -1; i < nelems; i++) {
1713 void *lower = (i == -1 ? lowbound : node->elems[i]);
1714 void *higher = (i+1 == nelems ? highbound : node->elems[i+1]);
1715 if (lower && higher && cmp(lower, higher) >= 0) {
1716 error("node %p: kid comparison [%d=%s,%d=%s] failed",
1717 node, i, lower, i+1, higher);
1718 }
1719 }
1720 }
1721
1722 /*
1723 * Check parent pointers: all non-NULL kids should have a
1724 * parent pointer coming back to this node.
1725 */
1726 for (i = 0; i < nkids; i++)
1727 if (node->kids[i]->parent != node) {
1728 error("node %p kid %d: parent ptr is %p not %p",
1729 node, i, node->kids[i]->parent, node);
1730 }
1731
1732
1733 /*
1734 * Now (finally!) recurse into subtrees.
1735 */
1736 count = nelems;
1737
1738 for (i = 0; i < nkids; i++) {
1739 void *lower = (i == 0 ? lowbound : node->elems[i-1]);
1740 void *higher = (i >= nelems ? highbound : node->elems[i]);
1741 int subcount = chknode(ctx, level+1, node->kids[i], lower, higher);
1742 if (node->counts[i] != subcount) {
1743 error("node %p kid %d: count says %d, subtree really has %d",
1744 node, i, node->counts[i], subcount);
1745 }
1746 count += subcount;
1747 }
1748
1749 return count;
1750}
1751
1752void verifytree(tree234 *tree, void **array, int arraylen) {
1753 chkctx ctx;
1754 int i;
1755 void *p;
1756
1757 ctx.treedepth = -1; /* depth unknown yet */
1758 ctx.elemcount = 0; /* no elements seen yet */
1759 /*
1760 * Verify validity of tree properties.
1761 */
1762 if (tree->root) {
1763 if (tree->root->parent != NULL)
1764 error("root->parent is %p should be null", tree->root->parent);
1765 chknode(&ctx, 0, tree->root, NULL, NULL);
1766 }
1767 printf("tree depth: %d\n", ctx.treedepth);
1768 /*
1769 * Enumerate the tree and ensure it matches up to the array.
1770 */
1771 for (i = 0; NULL != (p = index234(tree, i)); i++) {
1772 if (i >= arraylen)
1773 error("tree contains more than %d elements", arraylen);
1774 if (array[i] != p)
1775 error("enum at position %d: array says %s, tree says %s",
1776 i, array[i], p);
1777 }
1778 if (ctx.elemcount != i) {
1779 error("tree really contains %d elements, enum gave %d",
1780 ctx.elemcount, i);
1781 }
1782 if (i < arraylen) {
1783 error("enum gave only %d elements, array has %d", i, arraylen);
1784 }
1785 i = count234(tree);
1786 if (ctx.elemcount != i) {
1787 error("tree really contains %d elements, count234 gave %d",
1788 ctx.elemcount, i);
1789 }
1790}
1791void verify(void) { verifytree(tree, array, arraylen); }
1792
1793void internal_addtest(void *elem, int index, void *realret) {
1794 int i, j;
1795 void *retval;
1796
1797 if (arraysize < arraylen+1) {
1798 arraysize = arraylen+1+256;
1799 array = (array == NULL ? smalloc(arraysize*sizeof(*array)) :
1800 srealloc(array, arraysize*sizeof(*array)));
1801 }
1802
1803 i = index;
1804 /* now i points to the first element >= elem */
1805 retval = elem; /* expect elem returned (success) */
1806 for (j = arraylen; j > i; j--)
1807 array[j] = array[j-1];
1808 array[i] = elem; /* add elem to array */
1809 arraylen++;
1810
1811 if (realret != retval) {
1812 error("add: retval was %p expected %p", realret, retval);
1813 }
1814
1815 verify();
1816}
1817
1818void addtest(void *elem) {
1819 int i;
1820 void *realret;
1821
1822 realret = add234(tree, elem);
1823
1824 i = 0;
1825 while (i < arraylen && cmp(elem, array[i]) > 0)
1826 i++;
1827 if (i < arraylen && !cmp(elem, array[i])) {
1828 void *retval = array[i]; /* expect that returned not elem */
1829 if (realret != retval) {
1830 error("add: retval was %p expected %p", realret, retval);
1831 }
1832 } else
1833 internal_addtest(elem, i, realret);
1834}
1835
1836void addpostest(void *elem, int i) {
1837 void *realret;
1838
1839 realret = addpos234(tree, elem, i);
1840
1841 internal_addtest(elem, i, realret);
1842}
1843
1844void delpostest(int i) {
1845 int index = i;
1846 void *elem = array[i], *ret;
1847
1848 /* i points to the right element */
1849 while (i < arraylen-1) {
1850 array[i] = array[i+1];
1851 i++;
1852 }
1853 arraylen--; /* delete elem from array */
1854
1855 if (tree->cmp)
1856 ret = del234(tree, elem);
1857 else
1858 ret = delpos234(tree, index);
1859
1860 if (ret != elem) {
1861 error("del returned %p, expected %p", ret, elem);
1862 }
1863
1864 verify();
1865}
1866
1867void deltest(void *elem) {
1868 int i;
1869
1870 i = 0;
1871 while (i < arraylen && cmp(elem, array[i]) > 0)
1872 i++;
1873 if (i >= arraylen || cmp(elem, array[i]) != 0)
1874 return; /* don't do it! */
1875 delpostest(i);
1876}
1877
1878/* A sample data set and test utility. Designed for pseudo-randomness,
1879 * and yet repeatability. */
1880
1881/*
1882 * This random number generator uses the `portable implementation'
1883 * given in ANSI C99 draft N869. It assumes `unsigned' is 32 bits;
1884 * change it if not.
1885 */
1886int randomnumber(unsigned *seed) {
1887 *seed *= 1103515245;
1888 *seed += 12345;
1889 return ((*seed) / 65536) % 32768;
1890}
1891
1892int mycmp(void *av, void *bv) {
1893 char const *a = (char const *)av;
1894 char const *b = (char const *)bv;
1895 return strcmp(a, b);
1896}
1897
1898char *strings[] = {
1899 "0", "2", "3", "I", "K", "d", "H", "J", "Q", "N", "n", "q", "j", "i",
1900 "7", "G", "F", "D", "b", "x", "g", "B", "e", "v", "V", "T", "f", "E",
1901 "S", "8", "A", "k", "X", "p", "C", "R", "a", "o", "r", "O", "Z", "u",
1902 "6", "1", "w", "L", "P", "M", "c", "U", "h", "9", "t", "5", "W", "Y",
1903 "m", "s", "l", "4",
1904#if 0
1905 "a", "ab", "absque", "coram", "de",
1906 "palam", "clam", "cum", "ex", "e",
1907 "sine", "tenus", "pro", "prae",
1908 "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
1909 "penguin", "blancmange", "pangolin", "whale", "hedgehog",
1910 "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
1911 "murfl", "spoo", "breen", "flarn", "octothorpe",
1912 "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
1913 "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
1914 "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
1915 "wand", "ring", "amulet"
1916#endif
1917};
1918
1919#define NSTR lenof(strings)
1920
1921void findtest(void) {
1922 static const int rels[] = {
1923 REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT
1924 };
1925 static const char *const relnames[] = {
1926 "EQ", "GE", "LE", "LT", "GT"
1927 };
1928 int i, j, rel, index;
1929 char *p, *ret, *realret, *realret2;
1930 int lo, hi, mid, c;
1931
1932 for (i = 0; i < (int)NSTR; i++) {
1933 p = strings[i];
1934 for (j = 0; j < (int)(sizeof(rels)/sizeof(*rels)); j++) {
1935 rel = rels[j];
1936
1937 lo = 0; hi = arraylen-1;
1938 while (lo <= hi) {
1939 mid = (lo + hi) / 2;
1940 c = strcmp(p, array[mid]);
1941 if (c < 0)
1942 hi = mid-1;
1943 else if (c > 0)
1944 lo = mid+1;
1945 else
1946 break;
1947 }
1948
1949 if (c == 0) {
1950 if (rel == REL234_LT)
1951 ret = (mid > 0 ? array[--mid] : NULL);
1952 else if (rel == REL234_GT)
1953 ret = (mid < arraylen-1 ? array[++mid] : NULL);
1954 else
1955 ret = array[mid];
1956 } else {
1957 assert(lo == hi+1);
1958 if (rel == REL234_LT || rel == REL234_LE) {
1959 mid = hi;
1960 ret = (hi >= 0 ? array[hi] : NULL);
1961 } else if (rel == REL234_GT || rel == REL234_GE) {
1962 mid = lo;
1963 ret = (lo < arraylen ? array[lo] : NULL);
1964 } else
1965 ret = NULL;
1966 }
1967
1968 realret = findrelpos234(tree, p, NULL, rel, &index);
1969 if (realret != ret) {
1970 error("find(\"%s\",%s) gave %s should be %s",
1971 p, relnames[j], realret, ret);
1972 }
1973 if (realret && index != mid) {
1974 error("find(\"%s\",%s) gave %d should be %d",
1975 p, relnames[j], index, mid);
1976 }
1977 if (realret && rel == REL234_EQ) {
1978 realret2 = index234(tree, index);
1979 if (realret2 != realret) {
1980 error("find(\"%s\",%s) gave %s(%d) but %d -> %s",
1981 p, relnames[j], realret, index, index, realret2);
1982 }
1983 }
1984#if 0
1985 printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j],
1986 realret, index);
1987#endif
1988 }
1989 }
1990
1991 realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index);
1992 if (arraylen && (realret != array[0] || index != 0)) {
1993 error("find(NULL,GT) gave %s(%d) should be %s(0)",
1994 realret, index, array[0]);
1995 } else if (!arraylen && (realret != NULL)) {
1996 error("find(NULL,GT) gave %s(%d) should be NULL",
1997 realret, index);
1998 }
1999
2000 realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index);
2001 if (arraylen && (realret != array[arraylen-1] || index != arraylen-1)) {
2002 error("find(NULL,LT) gave %s(%d) should be %s(0)",
2003 realret, index, array[arraylen-1]);
2004 } else if (!arraylen && (realret != NULL)) {
2005 error("find(NULL,LT) gave %s(%d) should be NULL",
2006 realret, index);
2007 }
2008}
2009
2010void splittest(tree234 *tree, void **array, int arraylen) {
2011 int i;
2012 tree234 *tree3, *tree4;
2013 for (i = 0; i <= arraylen; i++) {
2014 tree3 = copytree234(tree, NULL, NULL);
2015 tree4 = splitpos234(tree3, i, false);
2016 verifytree(tree3, array, i);
2017 verifytree(tree4, array+i, arraylen-i);
2018 join234(tree3, tree4);
2019 freetree234(tree4); /* left empty by join */
2020 verifytree(tree3, array, arraylen);
2021 freetree234(tree3);
2022 }
2023}
2024
2025int main(void) {
2026 int in[NSTR];
2027 int i, j, k;
2028 int tworoot, tmplen;
2029 unsigned seed = 0;
2030 tree234 *tree2, *tree3, *tree4;
2031 int c;
2032
2033 setvbuf(stdout, NULL, _IOLBF, 0);
2034
2035 for (i = 0; i < (int)NSTR; i++) in[i] = 0;
2036 array = NULL;
2037 arraylen = arraysize = 0;
2038 tree = newtree234(mycmp);
2039 cmp = mycmp;
2040
2041 verify();
2042 for (i = 0; i < 10000; i++) {
2043 j = randomnumber(&seed);
2044 j %= NSTR;
2045 printf("trial: %d\n", i);
2046 if (in[j]) {
2047 printf("deleting %s (%d)\n", strings[j], j);
2048 deltest(strings[j]);
2049 in[j] = 0;
2050 } else {
2051 printf("adding %s (%d)\n", strings[j], j);
2052 addtest(strings[j]);
2053 in[j] = 1;
2054 }
2055 disptree(tree);
2056 findtest();
2057 }
2058
2059 while (arraylen > 0) {
2060 j = randomnumber(&seed);
2061 j %= arraylen;
2062 deltest(array[j]);
2063 }
2064
2065 freetree234(tree);
2066
2067 /*
2068 * Now try an unsorted tree. We don't really need to test
2069 * delpos234 because we know del234 is based on it, so it's
2070 * already been tested in the above sorted-tree code; but for
2071 * completeness we'll use it to tear down our unsorted tree
2072 * once we've built it.
2073 */
2074 tree = newtree234(NULL);
2075 cmp = NULL;
2076 verify();
2077 for (i = 0; i < 1000; i++) {
2078 printf("trial: %d\n", i);
2079 j = randomnumber(&seed);
2080 j %= NSTR;
2081 k = randomnumber(&seed);
2082 k %= count234(tree)+1;
2083 printf("adding string %s at index %d\n", strings[j], k);
2084 addpostest(strings[j], k);
2085 }
2086
2087 /*
2088 * While we have this tree in its full form, we'll take a copy
2089 * of it to use in split and join testing.
2090 */
2091 tree2 = copytree234(tree, NULL, NULL);
2092 verifytree(tree2, array, arraylen);/* check the copy is accurate */
2093 /*
2094 * Split tests. Split the tree at every possible point and
2095 * check the resulting subtrees.
2096 */
2097 tworoot = (!tree2->root->elems[1]);/* see if it has a 2-root */
2098 splittest(tree2, array, arraylen);
2099 /*
2100 * Now do the split test again, but on a tree that has a 2-root
2101 * (if the previous one didn't) or doesn't (if the previous one
2102 * did).
2103 */
2104 tmplen = arraylen;
2105 while ((!tree2->root->elems[1]) == tworoot) {
2106 delpos234(tree2, --tmplen);
2107 }
2108 printf("now trying splits on second tree\n");
2109 splittest(tree2, array, tmplen);
2110 freetree234(tree2);
2111
2112 /*
2113 * Back to the main testing of uncounted trees.
2114 */
2115 while (count234(tree) > 0) {
2116 printf("cleanup: tree size %d\n", count234(tree));
2117 j = randomnumber(&seed);
2118 j %= count234(tree);
2119 printf("deleting string %s from index %d\n", (char *)array[j], j);
2120 delpostest(j);
2121 }
2122 freetree234(tree);
2123
2124 /*
2125 * Finally, do some testing on split/join on _sorted_ trees. At
2126 * the same time, we'll be testing split on very small trees.
2127 */
2128 tree = newtree234(mycmp);
2129 cmp = mycmp;
2130 arraylen = 0;
2131 for (i = 0; i < 17; i++) {
2132 tree2 = copytree234(tree, NULL, NULL);
2133 splittest(tree2, array, arraylen);
2134 freetree234(tree2);
2135 if (i < 16)
2136 addtest(strings[i]);
2137 }
2138 freetree234(tree);
2139
2140 /*
2141 * Test silly cases of join: join(emptytree, emptytree), and
2142 * also ensure join correctly spots when sorted trees fail the
2143 * ordering constraint.
2144 */
2145 tree = newtree234(mycmp);
2146 tree2 = newtree234(mycmp);
2147 tree3 = newtree234(mycmp);
2148 tree4 = newtree234(mycmp);
2149 assert(mycmp(strings[0], strings[1]) < 0); /* just in case :-) */
2150 add234(tree2, strings[1]);
2151 add234(tree4, strings[0]);
2152 array[0] = strings[0];
2153 array[1] = strings[1];
2154 verifytree(tree, array, 0);
2155 verifytree(tree2, array+1, 1);
2156 verifytree(tree3, array, 0);
2157 verifytree(tree4, array, 1);
2158
2159 /*
2160 * So:
2161 * - join(tree,tree3) should leave both tree and tree3 unchanged.
2162 * - joinr(tree,tree2) should leave both tree and tree2 unchanged.
2163 * - join(tree4,tree3) should leave both tree3 and tree4 unchanged.
2164 * - join(tree, tree2) should move the element from tree2 to tree.
2165 * - joinr(tree4, tree3) should move the element from tree4 to tree3.
2166 * - join(tree,tree3) should return NULL and leave both unchanged.
2167 * - join(tree3,tree) should work and create a bigger tree in tree3.
2168 */
2169 assert(tree == join234(tree, tree3));
2170 verifytree(tree, array, 0);
2171 verifytree(tree3, array, 0);
2172 assert(tree2 == join234r(tree, tree2));
2173 verifytree(tree, array, 0);
2174 verifytree(tree2, array+1, 1);
2175 assert(tree4 == join234(tree4, tree3));
2176 verifytree(tree3, array, 0);
2177 verifytree(tree4, array, 1);
2178 assert(tree == join234(tree, tree2));
2179 verifytree(tree, array+1, 1);
2180 verifytree(tree2, array, 0);
2181 assert(tree3 == join234r(tree4, tree3));
2182 verifytree(tree3, array, 1);
2183 verifytree(tree4, array, 0);
2184 assert(NULL == join234(tree, tree3));
2185 verifytree(tree, array+1, 1);
2186 verifytree(tree3, array, 1);
2187 assert(tree3 == join234(tree3, tree));
2188 verifytree(tree3, array, 2);
2189 verifytree(tree, array, 0);
2190
2191 return 0;
2192}
2193
2194#endif
2195
2196#if 0 /* sorted list of strings might be useful */
2197{
2198 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
2199}
2200#endif