⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree234.c

📁 nsis是一个流传比较广的程序安装和解安装封装软件
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*     * Remove the root if it's undersize (it will contain only     * one child pointer, so just throw it away and replace it     * with its child). This might happen several times.     */    while (halves[half] && !halves[half]->elems[0])    {      LOG(("  root %p is undersize, throwing away\n", halves[half]));      halves[half] = halves[half]->kids[0];      sfree(halves[half]->parent);      halves[half]->parent = NULL;      LOG(("  new root is %p\n", halves[half]));    }    n = halves[half];    while (n)    {      void (*toward) (node234 * n, int ki, int *k, int *index);      int ni, merge;      /*       * Now we have a potentially undersize node on the       * right (if half==0) or left (if half==1). Sort it       * out, by merging with a neighbour or by transferring       * subtrees over. At this time we must also ensure that       * nodes are bigger than minimum, in case we need an       * element to merge two nodes below.       */      LOG(("  node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n", n,           n->kids[0], n->counts[0], n->elems[0], n->kids[1], n->counts[1],           n->elems[1], n->kids[2], n->counts[2], n->elems[2], n->kids[3],           n->counts[3]));      if (half == 1)      {        ki = 0;                 /* the kid we're interested in */        ni = 1;                 /* the neighbour */        merge = 0;              /* for merge: leftmost of the two */        toward = trans234_subtree_left;      } else      {        ki = (n->kids[3] ? 3 : n->kids[2] ? 2 : 1);        ni = ki - 1;        merge = ni;        toward = trans234_subtree_right;      }      sub = n->kids[ki];      if (sub && !sub->elems[1])      {        /*         * This node is undersized or minimum-size. If we         * can merge it with its neighbour, we do so;         * otherwise we must be able to transfer subtrees         * over to it until it is greater than minimum         * size.         */        int undersized = (!sub->elems[0]);        LOG(("  child %d is %ssize\n", ki,             undersized ? "under" : "minimum-"));        LOG(("  neighbour is %s\n",             n->kids[ni]->elems[2] ? "large" :             n->kids[ni]->elems[1] ? "medium" : "small"));        if (!n->kids[ni]->elems[1] ||            (undersized && !n->kids[ni]->elems[2]))        {          /*           * Neighbour is small, or possibly neighbour is           * medium and we are undersize.           */          trans234_subtree_merge(n, merge, NULL, NULL);          sub = n->kids[merge];          if (!n->elems[0])          {            /*             * n is empty, and hence must have been the             * root and needs to be removed.             */            assert(!n->parent);            LOG(("  shifting root!\n"));            halves[half] = sub;            halves[half]->parent = NULL;            sfree(n);          }        } else        {          /* Neighbour is big enough to move trees over. */          toward(n, ni, NULL, NULL);          if (undersized)            toward(n, ni, NULL, NULL);        }      }      n = sub;    }  }  t->root = halves[1];  return halves[0];}tree234 *splitpos234(tree234 * t, int index, int before){  tree234 *ret;  node234 *n;  int count;  count = countnode234(t->root);  if (index < 0 || index > count)    return NULL;                /* error */  ret = newtree234(t->cmp);  n = split234_internal(t, index);  if (before)  {    /* We want to return the ones before the index. */    ret->root = n;  } else  {    /*     * We want to keep the ones before the index and return the     * ones after.     */    ret->root = t->root;    t->root = n;  }  return ret;}tree234 *split234(tree234 * t, void *e, cmpfn234 cmp, int rel){  int before;  int index;  assert(rel != REL234_EQ);  if (rel == REL234_GT || rel == REL234_GE)  {    before = 1;    rel = (rel == REL234_GT ? REL234_LE : REL234_LT);  } else  {    before = 0;  }  if (!findrelpos234(t, e, cmp, rel, &index))    index = 0;  return splitpos234(t, index + 1, before);}static node234 *copynode234(node234 * n, copyfn234 copyfn,                            void *copyfnstate){  int i;  node234 *n2 = mknew(node234);  for (i = 0; i < 3; i++)  {    if (n->elems[i] && copyfn)      n2->elems[i] = copyfn(copyfnstate, n->elems[i]);    else      n2->elems[i] = n->elems[i];  }  for (i = 0; i < 4; i++)  {    if (n->kids[i])    {      n2->kids[i] = copynode234(n->kids[i], copyfn, copyfnstate);      n2->kids[i]->parent = n2;    } else    {      n2->kids[i] = NULL;    }    n2->counts[i] = n->counts[i];  }  return n2;}tree234 *copytree234(tree234 * t, copyfn234 copyfn, void *copyfnstate){  tree234 *t2;  t2 = newtree234(t->cmp);  t2->root = copynode234(t->root, copyfn, copyfnstate);  t2->root->parent = NULL;  return t2;}#ifdef TEST/* * Test code for the 2-3-4 tree. This code maintains an alternative * representation of the data in the tree, in an array (using the * obvious and slow insert and delete functions). After each tree * operation, the verify() function is called, which ensures all * the tree properties are preserved: *  - node->child->parent always equals node *  - tree->root->parent always equals NULL *  - number of kids == 0 or number of elements + 1; *  - tree has the same depth everywhere *  - every node has at least one element *  - subtree element counts are accurate *  - any NULL kid pointer is accompanied by a zero count *  - in a sorted tree: ordering property between elements of a *    node and elements of its children is preserved * and also ensures the list represented by the tree is the same * list it should be. (This last check also doubly verifies the * ordering properties, because the `same list it should be' is by * definition correctly ordered. It also ensures all nodes are * distinct, because the enum functions would get caught in a loop * if not.) */#include <stdarg.h>#define srealloc realloc/* * Error reporting function. */void error(char *fmt, ...){  va_list ap;  printf("ERROR: ");  va_start(ap, fmt);  vfprintf(stdout, fmt, ap);  va_end(ap);  printf("\n");}/* The array representation of the data. */void **array;int arraylen, arraysize;cmpfn234 cmp;/* The tree representation of the same data. */tree234 *tree;/* * Routines to provide a diagnostic printout of a tree. Currently * relies on every element in the tree being a one-character string * :-) */typedef struct {  char **levels;} dispctx;int dispnode(node234 * n, int level, dispctx * ctx){  if (level == 0)  {    int xpos = strlen(ctx->levels[0]);    int len;    if (n->elems[2])      len = sprintf(ctx->levels[0] + xpos, " %s%s%s",                    n->elems[0], n->elems[1], n->elems[2]);    else if (n->elems[1])      len = sprintf(ctx->levels[0] + xpos, " %s%s",                    n->elems[0], n->elems[1]);    else      len = sprintf(ctx->levels[0] + xpos, " %s", n->elems[0]);    return xpos + 1 + (len - 1) / 2;  } else  {    int xpos[4], nkids;    int nodelen, mypos, myleft, x, i;    xpos[0] = dispnode(n->kids[0], level - 3, ctx);    xpos[1] = dispnode(n->kids[1], level - 3, ctx);    nkids = 2;    if (n->kids[2])    {      xpos[2] = dispnode(n->kids[2], level - 3, ctx);      nkids = 3;    }    if (n->kids[3])    {      xpos[3] = dispnode(n->kids[3], level - 3, ctx);      nkids = 4;    }    if (nkids == 4)      mypos = (xpos[1] + xpos[2]) / 2;    else if (nkids == 3)      mypos = xpos[1];    else      mypos = (xpos[0] + xpos[1]) / 2;    nodelen = nkids * 2 - 1;    myleft = mypos - ((nodelen - 1) / 2);    assert(myleft >= xpos[0]);    assert(myleft + nodelen - 1 <= xpos[nkids - 1]);    x = strlen(ctx->levels[level]);    while (x <= xpos[0] && x < myleft)      ctx->levels[level][x++] = ' ';    while (x < myleft)      ctx->levels[level][x++] = '_';    if (nkids == 4)      x += sprintf(ctx->levels[level] + x, ".%s.%s.%s.",                   n->elems[0], n->elems[1], n->elems[2]);    else if (nkids == 3)      x += sprintf(ctx->levels[level] + x, ".%s.%s.",                   n->elems[0], n->elems[1]);    else      x += sprintf(ctx->levels[level] + x, ".%s.", n->elems[0]);    while (x < xpos[nkids - 1])      ctx->levels[level][x++] = '_';    ctx->levels[level][x] = '\0';    x = strlen(ctx->levels[level - 1]);    for (i = 0; i < nkids; i++)    {      int rpos, pos;      rpos = xpos[i];      if (i > 0 && i < nkids - 1)        pos = myleft + 2 * i;      else        pos = rpos;      if (rpos < pos)        rpos++;      while (x < pos && x < rpos)        ctx->levels[level - 1][x++] = ' ';      if (x == pos)        ctx->levels[level - 1][x++] = '|';      while (x < pos || x < rpos)        ctx->levels[level - 1][x++] = '_';      if (x == pos)        ctx->levels[level - 1][x++] = '|';    }    ctx->levels[level - 1][x] = '\0';    x = strlen(ctx->levels[level - 2]);    for (i = 0; i < nkids; i++)    {      int rpos = xpos[i];      while (x < rpos)        ctx->levels[level - 2][x++] = ' ';      ctx->levels[level - 2][x++] = '|';    }    ctx->levels[level - 2][x] = '\0';    return mypos;  }}void disptree(tree234 * t){  dispctx ctx;  char *leveldata;  int width = count234(t);  int ht = height234(t) * 3 - 2;  int i;  if (!t->root)  {    printf("[empty tree]\n");  }  leveldata = smalloc(ht * (width + 2));  ctx.levels = smalloc(ht * sizeof(char *));  for (i = 0; i < ht; i++)  {    ctx.levels[i] = leveldata + i * (width + 2);    ctx.levels[i][0] = '\0';  }  (void) dispnode(t->root, ht - 1, &ctx);  for (i = ht; i--;)    printf("%s\n", ctx.levels[i]);  sfree(ctx.levels);  sfree(leveldata);}typedef struct {  int treedepth;  int elemcount;} chkctx;intchknode(chkctx * ctx, int level, node234 * node,        void *lowbound, void *highbound){  int nkids, nelems;  int i;  int count;  /* Count the non-NULL kids. */  for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);  /* Ensure no kids beyond the first NULL are non-NULL. */  for (i = nkids; i < 4; i++)    if (node->kids[i])    {      error("node %p: nkids=%d but kids[%d] non-NULL", node, nkids, i);    } else if (node->counts[i])    {      error("node %p: kids[%d] NULL but count[%d]=%d nonzero",            node, i, i, node->counts[i]);    }  /* Count the non-NULL elements. */  for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);  /* Ensure no elements beyond the first NULL are non-NULL. */  for (i = nelems; i < 3; i++)    if (node->elems[i])    {      error("node %p: nelems=%d but elems[%d] non-NULL", node, nelems, i);    }  if (nkids == 0)  {    /*     * If nkids==0, this is a leaf node; verify that the tree     * depth is the same everywhere.     */    if (ctx->treedepth < 0)      ctx->treedepth = level;   /* we didn't know the depth yet */    else if (ctx->treedepth != level)      error("node %p: leaf at depth %d, previously seen depth %d",            node, level, ctx->treedepth);  } else  {    /*     * If nkids != 0, then it should be nelems+1, unless nelems     * is 0 in which case nkids should also be 0 (and so we     * shouldn't be in this condition at all).     */    int shouldkids = (nelems ? nelems + 1 : 0);    if (nkids != shouldkids)    {      error("node %p: %d elems should mean %d kids but has %d",            node, nelems, shouldkids, nkids);    }  }  /*   * nelems should be at least 1.   */  if (nelems == 0)  {    error("node %p: no elems", node, nkids);  }  /*   * Add nelems to the running element count of the whole tree.   */  ctx->elemcount += nelems;  /*   * Check ordering property: all elements should be strictly >   * lowbound, strictly < highbound, and strictly < each other in   * sequence. (lowbound and highbound are NULL at edges of tree   * - both NULL at root node - and NULL is considered to be <   * everything and > everything. IYSWIM.)   */  if (cmp)  {    for (i = -1; i < nelems; i++)    {      void *lower = (i == -1 ? lowbound : node->elems[i]);      void *higher = (i + 1 == nelems ? highbound : node->elems[i + 1]);      if (lower && higher && cmp(lower, higher) >= 0)      {        error("node %p: kid comparison [%d=%s,%d=%s] failed",              node, i, lower, i + 1, higher);      }    }  }  /*   * Check parent pointers: all non-NULL kids should have a   * parent pointer coming back to this node.   */  for (i = 0; i < nkids; i++)    if (node->kids[i]->parent != node)    {      error("node %p kid %d: parent ptr is %p not %p",            node, i, node->kids[i]->parent, node);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -