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

📄 tree234.c

📁 nsis是一个流传比较广的程序安装和解安装封装软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  n->counts[3] = 0;  n->elems[2] = NULL;  if (k)  {    LOG(("    before: k,index = %d,%d\n", (*k), (*index)));    if ((*k) == ki + 1)    {      (*k)--;      (*index) += leftlen + 1;    } else if ((*k) > ki + 1)    {      (*k)--;    }    LOG(("    after: k,index = %d,%d\n", (*k), (*index)));  }  LOG(("    parent %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]));  LOG(("    merged %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       left,       left->kids[0], left->counts[0], left->elems[0],       left->kids[1], left->counts[1], left->elems[1],       left->kids[2], left->counts[2], left->elems[2],       left->kids[3], left->counts[3]));}/* * Delete an element e in a 2-3-4 tree. Does not free the element, * merely removes all links to it from the tree nodes. */static void *delpos234_internal(tree234 * t, int index){  node234 *n;  void *retval;  int ki, i;  retval = NULL;  n = t->root;                  /* by assumption this is non-NULL */  LOG(("deleting item %d from tree %p\n", index, t));  while (1)  {    node234 *sub;    LOG(("  node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d index=%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], index));    if (index <= n->counts[0])    {      ki = 0;    } else if (index -= n->counts[0] + 1, index <= n->counts[1])    {      ki = 1;    } else if (index -= n->counts[1] + 1, index <= n->counts[2])    {      ki = 2;    } else if (index -= n->counts[2] + 1, index <= n->counts[3])    {      ki = 3;    } else    {      assert(0);                /* can't happen */    }    if (!n->kids[0])      break;                    /* n is a leaf node; we're here! */    /*     * Check to see if we've found our target element. If so,     * we must choose a new target (we'll use the old target's     * successor, which will be in a leaf), move it into the     * place of the old one, continue down to the leaf and     * delete the old copy of the new target.     */    if (index == n->counts[ki])    {      node234 *m;      LOG(("  found element in internal node, index %d\n", ki));      assert(n->elems[ki]);     /* must be a kid _before_ an element */      ki++;      index = 0;      for (m = n->kids[ki]; m->kids[0]; m = m->kids[0])        continue;      LOG(("  replacing with element \"%s\" from leaf node %p\n",           m->elems[0], m));      retval = n->elems[ki - 1];      n->elems[ki - 1] = m->elems[0];    }    /*     * Recurse down to subtree ki. If it has only one element,     * we have to do some transformation to start with.     */    LOG(("  moving to subtree %d\n", ki));    sub = n->kids[ki];    if (!sub->elems[1])    {      LOG(("  subtree has only one element!\n"));      if (ki > 0 && n->kids[ki - 1]->elems[1])      {        /*         * Child ki has only one element, but child         * ki-1 has two or more. So we need to move a         * subtree from ki-1 to ki.         */        trans234_subtree_right(n, ki - 1, &ki, &index);      } else if (ki < 3 && n->kids[ki + 1] && n->kids[ki + 1]->elems[1])      {        /*         * Child ki has only one element, but ki+1 has         * two or more. Move a subtree from ki+1 to ki.         */        trans234_subtree_left(n, ki + 1, &ki, &index);      } else      {        /*         * ki is small with only small neighbours. Pick a         * neighbour and merge with it.         */        trans234_subtree_merge(n, ki > 0 ? ki - 1 : ki, &ki, &index);        sub = n->kids[ki];        if (!n->elems[0])        {          /*           * The root is empty and needs to be           * removed.           */          LOG(("  shifting root!\n"));          t->root = sub;          sub->parent = NULL;          sfree(n);          n = NULL;        }      }    }    if (n)      n->counts[ki]--;    n = sub;  }  /*   * Now n is a leaf node, and ki marks the element number we   * want to delete. We've already arranged for the leaf to be   * bigger than minimum size, so let's just go to it.   */  assert(!n->kids[0]);  if (!retval)    retval = n->elems[ki];  for (i = ki; i < 2 && n->elems[i + 1]; i++)    n->elems[i] = n->elems[i + 1];  n->elems[i] = NULL;  /*   * It's just possible that we have reduced the leaf to zero   * size. This can only happen if it was the root - so destroy   * it and make the tree empty.   */  if (!n->elems[0])  {    LOG(("  removed last element in tree, destroying empty root\n"));    assert(n == t->root);    sfree(n);    t->root = NULL;  }  return retval;                /* finished! */}void *delpos234(tree234 * t, int index){  if (index < 0 || index >= countnode234(t->root))    return NULL;  return delpos234_internal(t, index);}void *del234(tree234 * t, void *e){  int index;  if (!findrelpos234(t, e, NULL, REL234_EQ, &index))    return NULL;                /* it wasn't in there anyway */  return delpos234_internal(t, index);  /* it's there; delete it. */}/* * Join two subtrees together with a separator element between * them, given their relative height. *  * (Height<0 means the left tree is shorter, >0 means the right * tree is shorter, =0 means (duh) they're equal.) *  * It is assumed that any checks needed on the ordering criterion * have _already_ been done. *  * The value returned in `height' is 0 or 1 depending on whether the * resulting tree is the same height as the original larger one, or * one higher. */static node234 *join234_internal(node234 * left, void *sep,                                 node234 * right, int *height){  node234 *root, *node;  int relht = *height;  int ki;  LOG(("  join: joining %p \"%s\" %p, relative height is %d\n",       left, sep, right, relht));  if (relht == 0)  {    /*     * The trees are the same height. Create a new one-element     * root containing the separator and pointers to the two     * nodes.     */    node234 *newroot;    newroot = mknew(node234);    newroot->kids[0] = left;    newroot->counts[0] = countnode234(left);    newroot->elems[0] = sep;    newroot->kids[1] = right;    newroot->counts[1] = countnode234(right);    newroot->elems[1] = NULL;    newroot->kids[2] = NULL;    newroot->counts[2] = 0;    newroot->elems[2] = NULL;    newroot->kids[3] = NULL;    newroot->counts[3] = 0;    newroot->parent = NULL;    if (left)      left->parent = newroot;    if (right)      right->parent = newroot;    *height = 1;    LOG(("  join: same height, brand new root\n"));    return newroot;  }  /*   * This now works like the addition algorithm on the larger   * tree. We're replacing a single kid pointer with two kid   * pointers separated by an element; if that causes the node to   * overload, we split it in two, move a separator element up to   * the next node, and repeat.   */  if (relht < 0)  {    /*     * Left tree is shorter. Search down the right tree to find     * the pointer we're inserting at.     */    node = root = right;    while (++relht < 0)    {      node = node->kids[0];    }    ki = 0;    right = node->kids[ki];  } else  {    /*     * Right tree is shorter; search down the left to find the     * pointer we're inserting at.     */    node = root = left;    while (--relht > 0)    {      if (node->elems[2])        node = node->kids[3];      else if (node->elems[1])        node = node->kids[2];      else        node = node->kids[1];    }    if (node->elems[2])      ki = 3;    else if (node->elems[1])      ki = 2;    else      ki = 1;    left = node->kids[ki];  }  /*   * Now proceed as for addition.   */  *height = add234_insert(left, sep, right, &root, node, ki);  return root;}static int height234(tree234 * t){  int level = 0;  node234 *n = t->root;  while (n)  {    level++;    n = n->kids[0];  }  return level;}tree234 *join234(tree234 * t1, tree234 * t2){  int size2 = countnode234(t2->root);  if (size2 > 0)  {    void *element;    int relht;    if (t1->cmp)    {      element = index234(t2, 0);      element = findrelpos234(t1, element, NULL, REL234_GE, NULL);      if (element)        return NULL;    }    element = delpos234(t2, 0);    relht = height234(t1) - height234(t2);    t1->root = join234_internal(t1->root, element, t2->root, &relht);    t2->root = NULL;  }  return t1;}tree234 *join234r(tree234 * t1, tree234 * t2){  int size1 = countnode234(t1->root);  if (size1 > 0)  {    void *element;    int relht;    if (t2->cmp)    {      element = index234(t1, size1 - 1);      element = findrelpos234(t2, element, NULL, REL234_LE, NULL);      if (element)        return NULL;    }    element = delpos234(t1, size1 - 1);    relht = height234(t1) - height234(t2);    t2->root = join234_internal(t1->root, element, t2->root, &relht);    t1->root = NULL;  }  return t2;}/* * Split out the first <index> elements in a tree and return a * pointer to the root node. Leave the root node of the remainder * in t. */static node234 *split234_internal(tree234 * t, int index){  node234 *halves[2], *n, *sib, *sub;  node234 *lparent, *rparent;  int ki, pki=0, i, half, lcount, rcount;  n = t->root;  LOG(("splitting tree %p at point %d\n", t, index));  /*   * Easy special cases. After this we have also dealt completely   * with the empty-tree case and we can assume the root exists.   */  if (index == 0)               /* return nothing */    return NULL;  if (index == countnode234(t->root))  {                             /* return the whole tree */    node234 *ret = t->root;    t->root = NULL;    return ret;  }  /*   * Search down the tree to find the split point.   */  lparent = rparent = NULL;  while (n)  {    LOG(("  node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d index=%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], index));    lcount = index;    rcount = countnode234(n) - lcount;    if (index <= n->counts[0])    {      ki = 0;    } else if (index -= n->counts[0] + 1, index <= n->counts[1])    {      ki = 1;    } else if (index -= n->counts[1] + 1, index <= n->counts[2])    {      ki = 2;    } else    {      index -= n->counts[2] + 1;      ki = 3;    }    LOG(("  splitting at subtree %d\n", ki));    sub = n->kids[ki];    LOG(("  splitting at child index %d\n", ki));    /*     * Split the node, put halves[0] on the right of the left     * one and halves[1] on the left of the right one, put the     * new node pointers in halves[0] and halves[1], and go up     * a level.     */    sib = mknew(node234);    for (i = 0; i < 3; i++)    {      if (i + ki < 3 && n->elems[i + ki])      {        sib->elems[i] = n->elems[i + ki];        sib->kids[i + 1] = n->kids[i + ki + 1];        if (sib->kids[i + 1])          sib->kids[i + 1]->parent = sib;        sib->counts[i + 1] = n->counts[i + ki + 1];        n->elems[i + ki] = NULL;        n->kids[i + ki + 1] = NULL;        n->counts[i + ki + 1] = 0;      } else      {        sib->elems[i] = NULL;        sib->kids[i + 1] = NULL;        sib->counts[i + 1] = 0;      }    }    if (lparent)    {      lparent->kids[pki] = n;      lparent->counts[pki] = lcount;      n->parent = lparent;      rparent->kids[0] = sib;      rparent->counts[0] = rcount;      sib->parent = rparent;    } else    {      halves[0] = n;      n->parent = NULL;      halves[1] = sib;      sib->parent = NULL;    }    lparent = n;    rparent = sib;    pki = ki;    LOG(("  left 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]));    LOG(("  right node %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",         sib, sib->kids[0], sib->counts[0], sib->elems[0], sib->kids[1],         sib->counts[1], sib->elems[1], sib->kids[2], sib->counts[2],         sib->elems[2], sib->kids[3], sib->counts[3]));    n = sub;  }  /*   * We've come off the bottom here, so we've successfully split   * the tree into two equally high subtrees. The only problem is   * that some of the nodes down the fault line will be smaller   * than the minimum permitted size. (Since this is a 2-3-4   * tree, that means they'll be zero-element one-child nodes.)   */  LOG(("  fell off bottom, lroot is %p, rroot is %p\n",       halves[0], halves[1]));  lparent->counts[pki] = rparent->counts[0] = 0;  lparent->kids[pki] = rparent->kids[0] = NULL;  /*   * So now we go back down the tree from each of the two roots,   * fixing up undersize nodes.   */  for (half = 0; half < 2; half++)  {

⌨️ 快捷键说明

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