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

📄 tree234.c

📁 nsis是一个流传比较广的程序安装和解安装封装软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (index < 0 ||              /* index out of range */      t->cmp)                   /* tree is sorted */    return NULL;                /* return failure */  return add234_internal(t, e, index);  /* this checks the upper bound */}/* * Look up the element at a given numeric index in a 2-3-4 tree. * Returns NULL if the index is out of range. */void *index234(tree234 * t, int index){  node234 *n;  if (!t->root)    return NULL;                /* tree is empty */  if (index < 0 || index >= countnode234(t->root))    return NULL;                /* out of range */  n = t->root;  while (n)  {    if (index < n->counts[0])      n = n->kids[0];    else if (index -= n->counts[0] + 1, index < 0)      return n->elems[0];    else if (index < n->counts[1])      n = n->kids[1];    else if (index -= n->counts[1] + 1, index < 0)      return n->elems[1];    else if (index < n->counts[2])      n = n->kids[2];    else if (index -= n->counts[2] + 1, index < 0)      return n->elems[2];    else      n = n->kids[3];  }  /* We shouldn't ever get here. I wonder how we did. */  return NULL;}/* * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not * found. e is always passed as the first argument to cmp, so cmp * can be an asymmetric function if desired. cmp can also be passed * as NULL, in which case the compare function from the tree proper * will be used. */void *findrelpos234(tree234 * t, void *e, cmpfn234 cmp, int relation,                    int *index){  node234 *n;  void *ret;  int c;  int idx, ecount, kcount, cmpret;  if (t->root == NULL)    return NULL;  if (cmp == NULL)    cmp = t->cmp;  n = t->root;  /*   * Attempt to find the element itself.   */  idx = 0;  ecount = -1;  /*   * Prepare a fake `cmp' result if e is NULL.   */  cmpret = 0;  if (e == NULL)  {    assert(relation == REL234_LT || relation == REL234_GT);    if (relation == REL234_LT)      cmpret = +1;              /* e is a max: always greater */    else if (relation == REL234_GT)      cmpret = -1;              /* e is a min: always smaller */  }  while (1)  {    for (kcount = 0; kcount < 4; kcount++)    {      if (kcount >= 3 || n->elems[kcount] == NULL ||          (c = cmpret ? cmpret : cmp(e, n->elems[kcount])) < 0)      {        break;      }      if (n->kids[kcount])        idx += n->counts[kcount];      if (c == 0)      {        ecount = kcount;        break;      }      idx++;    }    if (ecount >= 0)      break;    if (n->kids[kcount])      n = n->kids[kcount];    else      break;  }  if (ecount >= 0)  {    /*     * We have found the element we're looking for. It's     * n->elems[ecount], at tree index idx. If our search     * relation is EQ, LE or GE we can now go home.     */    if (relation != REL234_LT && relation != REL234_GT)    {      if (index)        *index = idx;      return n->elems[ecount];    }    /*     * Otherwise, we'll do an indexed lookup for the previous     * or next element. (It would be perfectly possible to     * implement these search types in a non-counted tree by     * going back up from where we are, but far more fiddly.)     */    if (relation == REL234_LT)      idx--;    else      idx++;  } else  {    /*     * We've found our way to the bottom of the tree and we     * know where we would insert this node if we wanted to:     * we'd put it in in place of the (empty) subtree     * n->kids[kcount], and it would have index idx     *      * But the actual element isn't there. So if our search     * relation is EQ, we're doomed.     */    if (relation == REL234_EQ)      return NULL;    /*     * Otherwise, we must do an index lookup for index idx-1     * (if we're going left - LE or LT) or index idx (if we're     * going right - GE or GT).     */    if (relation == REL234_LT || relation == REL234_LE)    {      idx--;    }  }  /*   * We know the index of the element we want; just call index234   * to do the rest. This will return NULL if the index is out of   * bounds, which is exactly what we want.   */  ret = index234(t, idx);  if (ret && index)    *index = idx;  return ret;}void *find234(tree234 * t, void *e, cmpfn234 cmp){  return findrelpos234(t, e, cmp, REL234_EQ, NULL);}void *findrel234(tree234 * t, void *e, cmpfn234 cmp, int relation){  return findrelpos234(t, e, cmp, relation, NULL);}void *findpos234(tree234 * t, void *e, cmpfn234 cmp, int *index){  return findrelpos234(t, e, cmp, REL234_EQ, index);}/* * Tree transformation used in delete and split: move a subtree * right, from child ki of a node to the next child. Update k and * index so that they still point to the same place in the * transformed tree. Assumes the destination child is not full, and * that the source child does have a subtree to spare. Can cope if * the destination child is undersized. *  *                . C .                     . B . *               /     \     ->            /     \ * [more] a A b B c   d D e      [more] a A b   c C d D e *  *                 . C .                     . B . *                /     \    ->             /     \ *  [more] a A b B c     d        [more] a A b   c C d */static void trans234_subtree_right(node234 * n, int ki, int *k, int *index){  node234 *src, *dest;  int i, srclen, adjust;  src = n->kids[ki];  dest = n->kids[ki + 1];  LOG(("  trans234_subtree_right(%p, %d):\n", n, ki));  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(("    src %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       src,       src->kids[0], src->counts[0], src->elems[0],       src->kids[1], src->counts[1], src->elems[1],       src->kids[2], src->counts[2], src->elems[2],       src->kids[3], src->counts[3]));  LOG(("    dest %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       dest,       dest->kids[0], dest->counts[0], dest->elems[0],       dest->kids[1], dest->counts[1], dest->elems[1],       dest->kids[2], dest->counts[2], dest->elems[2],       dest->kids[3], dest->counts[3]));  /*   * Move over the rest of the destination node to make space.   */  dest->kids[3] = dest->kids[2];  dest->counts[3] = dest->counts[2];  dest->elems[2] = dest->elems[1];  dest->kids[2] = dest->kids[1];  dest->counts[2] = dest->counts[1];  dest->elems[1] = dest->elems[0];  dest->kids[1] = dest->kids[0];  dest->counts[1] = dest->counts[0];  /* which element to move over */  i = (src->elems[2] ? 2 : src->elems[1] ? 1 : 0);  dest->elems[0] = n->elems[ki];  n->elems[ki] = src->elems[i];  src->elems[i] = NULL;  dest->kids[0] = src->kids[i + 1];  dest->counts[0] = src->counts[i + 1];  src->kids[i + 1] = NULL;  src->counts[i + 1] = 0;  if (dest->kids[0])    dest->kids[0]->parent = dest;  adjust = dest->counts[0] + 1;  n->counts[ki] -= adjust;  n->counts[ki + 1] += adjust;  srclen = n->counts[ki];  if (k)  {    LOG(("    before: k,index = %d,%d\n", (*k), (*index)));    if ((*k) == ki && (*index) > srclen)    {      (*index) -= srclen + 1;      (*k)++;    } else if ((*k) == ki + 1)    {      (*index) += adjust;    }    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(("    src %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       src,       src->kids[0], src->counts[0], src->elems[0],       src->kids[1], src->counts[1], src->elems[1],       src->kids[2], src->counts[2], src->elems[2],       src->kids[3], src->counts[3]));  LOG(("    dest %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       dest,       dest->kids[0], dest->counts[0], dest->elems[0],       dest->kids[1], dest->counts[1], dest->elems[1],       dest->kids[2], dest->counts[2], dest->elems[2],       dest->kids[3], dest->counts[3]));}/* * Tree transformation used in delete and split: move a subtree * left, from child ki of a node to the previous child. Update k * and index so that they still point to the same place in the * transformed tree. Assumes the destination child is not full, and * that the source child does have a subtree to spare. Can cope if * the destination child is undersized.  * *      . B .                             . C . *     /     \                ->         /     \ *  a A b   c C d D e [more]      a A b B c   d D e [more] * *     . A .                             . B . *    /     \                 ->        /     \ *   a   b B c C d [more]            a A b   c C d [more] */static void trans234_subtree_left(node234 * n, int ki, int *k, int *index){  node234 *src, *dest;  int i, adjust;  src = n->kids[ki];  dest = n->kids[ki - 1];  LOG(("  trans234_subtree_left(%p, %d):\n", n, ki));  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(("    dest %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       dest,       dest->kids[0], dest->counts[0], dest->elems[0],       dest->kids[1], dest->counts[1], dest->elems[1],       dest->kids[2], dest->counts[2], dest->elems[2],       dest->kids[3], dest->counts[3]));  LOG(("    src %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       src,       src->kids[0], src->counts[0], src->elems[0],       src->kids[1], src->counts[1], src->elems[1],       src->kids[2], src->counts[2], src->elems[2],       src->kids[3], src->counts[3]));  /* where in dest to put it */  i = (dest->elems[1] ? 2 : dest->elems[0] ? 1 : 0);  dest->elems[i] = n->elems[ki - 1];  n->elems[ki - 1] = src->elems[0];  dest->kids[i + 1] = src->kids[0];  dest->counts[i + 1] = src->counts[0];  if (dest->kids[i + 1])    dest->kids[i + 1]->parent = dest;  /*   * Move over the rest of the source node.   */  src->kids[0] = src->kids[1];  src->counts[0] = src->counts[1];  src->elems[0] = src->elems[1];  src->kids[1] = src->kids[2];  src->counts[1] = src->counts[2];  src->elems[1] = src->elems[2];  src->kids[2] = src->kids[3];  src->counts[2] = src->counts[3];  src->elems[2] = NULL;  src->kids[3] = NULL;  src->counts[3] = 0;  adjust = dest->counts[i + 1] + 1;  n->counts[ki] -= adjust;  n->counts[ki - 1] += adjust;  if (k)  {    LOG(("    before: k,index = %d,%d\n", (*k), (*index)));    if ((*k) == ki)    {      (*index) -= adjust;      if ((*index) < 0)      {        (*index) += n->counts[ki - 1] + 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(("    dest %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       dest,       dest->kids[0], dest->counts[0], dest->elems[0],       dest->kids[1], dest->counts[1], dest->elems[1],       dest->kids[2], dest->counts[2], dest->elems[2],       dest->kids[3], dest->counts[3]));  LOG(("    src %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       src,       src->kids[0], src->counts[0], src->elems[0],       src->kids[1], src->counts[1], src->elems[1],       src->kids[2], src->counts[2], src->elems[2],       src->kids[3], src->counts[3]));}/* * Tree transformation used in delete and split: merge child nodes * ki and ki+1 of a node. Update k and index so that they still * point to the same place in the transformed tree. Assumes both * children _are_ sufficiently small. * *      . B .                . *     /     \     ->        | *  a A b   c C d      a A b B c C d *  * This routine can also cope with either child being undersized: *  *     . A .                 . *    /     \      ->        | *   a     b B c         a A b B c * *    . A .                  . *   /     \       ->        | *  a   b B c C d      a A b B c C d */static void trans234_subtree_merge(node234 * n, int ki, int *k, int *index){  node234 *left, *right;  int i, leftlen, rightlen, lsize, rsize;  left = n->kids[ki];  leftlen = n->counts[ki];  right = n->kids[ki + 1];  rightlen = n->counts[ki + 1];  LOG(("  trans234_subtree_merge(%p, %d):\n", n, ki));  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(("    left %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]));  LOG(("    right %p: %p/%d \"%s\" %p/%d \"%s\" %p/%d \"%s\" %p/%d\n",       right,       right->kids[0], right->counts[0], right->elems[0],       right->kids[1], right->counts[1], right->elems[1],       right->kids[2], right->counts[2], right->elems[2],       right->kids[3], right->counts[3]));  assert(!left->elems[2] && !right->elems[2]);  /* neither is large! */  lsize = (left->elems[1] ? 2 : left->elems[0] ? 1 : 0);  rsize = (right->elems[1] ? 2 : right->elems[0] ? 1 : 0);  left->elems[lsize] = n->elems[ki];  for (i = 0; i < rsize + 1; i++)  {    left->kids[lsize + 1 + i] = right->kids[i];    left->counts[lsize + 1 + i] = right->counts[i];    if (left->kids[lsize + 1 + i])      left->kids[lsize + 1 + i]->parent = left;    if (i < rsize)      left->elems[lsize + 1 + i] = right->elems[i];  }  n->counts[ki] += rightlen + 1;  sfree(right);  /*   * Move the rest of n up by one.   */  for (i = ki + 1; i < 3; i++)  {    n->kids[i] = n->kids[i + 1];    n->counts[i] = n->counts[i + 1];  }  for (i = ki; i < 2; i++)  {    n->elems[i] = n->elems[i + 1];  }  n->kids[3] = NULL;

⌨️ 快捷键说明

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