Пример #1
0
/* Find or insert datum into search tree.
   KEY is the key to be located, ROOTP is the address of tree root,
   COMPAR the ordering function.  */
void *
__tsearch (const void *key, void **vrootp, __compar_fn_t compar)
{
  node q;
  node *parentp = NULL, *gparentp = NULL;
  node *rootp = (node *) vrootp;
  node *nextp;
  int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler.  */

  if (rootp == NULL)
    return NULL;

  /* This saves some additional tests below.  */
  if (*rootp != NULL)
    (*rootp)->red = 0;

  CHECK_TREE (*rootp);

  nextp = rootp;
  while (*nextp != NULL)
    {
      node root = *rootp;
      r = (*compar) (key, root->key);
      if (r == 0)
	return root;

      maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
      /* If that did any rotations, parentp and gparentp are now garbage.
	 That doesn't matter, because the values they contain are never
	 used again in that case.  */

      nextp = r < 0 ? &root->left : &root->right;
      if (*nextp == NULL)
	break;

      gparentp = parentp;
      parentp = rootp;
      rootp = nextp;

      gp_r = p_r;
      p_r = r;
    }

  q = (struct node_t *) malloc (sizeof (struct node_t));
  if (q != NULL)
    {
      *nextp = q;			/* link new node to old */
      q->key = key;			/* initialize new node */
      q->red = 1;
      q->left = q->right = NULL;

      if (nextp != rootp)
	/* There may be two red edges in a row now, which we must avoid by
	   rotating the tree.  */
	maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
    }

  return q;
}
Пример #2
0
/**
 * Find or insert datum with given key into search tree. rootp
 * is the address of tree root, cmpfun the ordering function.
 */
GtKeytype gt_rbt_search(const GtKeytype key,
                        bool *nodecreated,
                        GtRBTnode **rootp,
                        GtDictcomparefunction cmpfun,
                        void *cmpinfo)
{
  GtRBTnode *newnode,
          **parentp = NULL,
          **gparentp = NULL,
          **nextp;
          int r = 0,
              p_r = 0,
              gp_r = 0;   /* No they might not, Mr Compiler. */

  if (rootp == NULL)
  {
    *nodecreated = false;
    return GtKeytypeerror;
  }

  /*
     This saves some additional tests below.
   */
  if (*rootp != NULL)
  {
    (*rootp)->red = false;
  }
  CHECK_TREE (*rootp);
  nextp = rootp;
  while (*nextp != NULL)
  {
    GtRBTnode *root = *rootp;

    r = cmpfun (key, root->key, cmpinfo);
    if (r == 0)
    {
      *nodecreated = false;
      return root->key;
    }

    maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
    /*
     * If that did any rotations, parentp and gparentp are now garbage. That
     * doesn't matter, because the values they contain are never used again in
     * that case.
     */

    nextp = r < 0 ? &root->left : &root->right;
    if (*nextp == NULL)
    {
      break;
    }

    gparentp = parentp;
    parentp = rootp;
    rootp = nextp;

    gp_r = p_r;
    p_r = r;
  }

  newnode = (GtRBTnode *) gt_malloc (sizeof (GtRBTnode));
  *nextp = newnode;                    /* link new node to old */
  newnode->key = key;                  /* initialize new node */
  newnode->red = true;
  newnode->left = NULL;
  newnode->right = NULL;
  if (nextp != rootp)
  {
    /*
       There may be two red edges in a row now, which we must
       avoid by rotating the tree.
     */
    maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1UL);
  }
  *nodecreated = true;
  return newnode->key;
}
Пример #3
0
/* Find or insert datum into search tree.
   KEY is the key to be located, ROOTP is the address of tree root,
   COMPAR the ordering function.  */
void *
__tsearch (const void *key, void **vrootp, __compar_fn_t compar)
{
  node q, root;
  node *parentp = NULL, *gparentp = NULL;
  node *rootp = (node *) vrootp;
  node *nextp;
  int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler.  */

#ifdef USE_MALLOC_LOW_BIT
  static_assert (alignof (max_align_t) > 1, "malloc must return aligned ptrs");
#endif

  if (rootp == NULL)
    return NULL;

  /* This saves some additional tests below.  */
  root = DEREFNODEPTR(rootp);
  if (root != NULL)
    SETBLACK(root);

  CHECK_TREE (root);

  nextp = rootp;
  while (DEREFNODEPTR(nextp) != NULL)
    {
      root = DEREFNODEPTR(rootp);
      r = (*compar) (key, root->key);
      if (r == 0)
	return root;

      maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
      /* If that did any rotations, parentp and gparentp are now garbage.
	 That doesn't matter, because the values they contain are never
	 used again in that case.  */

      nextp = r < 0 ? LEFTPTR(root) : RIGHTPTR(root);
      if (DEREFNODEPTR(nextp) == NULL)
	break;

      gparentp = parentp;
      parentp = rootp;
      rootp = nextp;

      gp_r = p_r;
      p_r = r;
    }

  q = (struct node_t *) malloc (sizeof (struct node_t));
  if (q != NULL)
    {
      /* Make sure the malloc implementation returns naturally aligned
	 memory blocks when expected.  Or at least even pointers, so we
	 can use the low bit as red/black flag.  Even though we have a
	 static_assert to make sure alignof (max_align_t) > 1 there could
	 be an interposed malloc implementation that might cause havoc by
	 not obeying the malloc contract.  */
#ifdef USE_MALLOC_LOW_BIT
      assert (((uintptr_t) q & (uintptr_t) 0x1) == 0);
#endif
      SETNODEPTR(nextp,q);		/* link new node to old */
      q->key = key;			/* initialize new node */
      SETRED(q);
      SETLEFT(q,NULL);
      SETRIGHT(q,NULL);

      if (nextp != rootp)
	/* There may be two red edges in a row now, which we must avoid by
	   rotating the tree.  */
	maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
    }

  return q;
}