Beispiel #1
0
/*
 * mm_remove_children - Remove the node from the Binary Tree as long as it has two children
 */
void *mm_remove_children(void *root, void *bp)
{
    void *parent_node = mm_parent(root, bp);
    void *replacement = mm_replace(LEFT(bp));
    void *new_bp;

    /* Remove the replacement and store the new bp */

    new_bp = mm_remove(LEFT(bp), replacement);

    SETLEFT(replacement, new_bp);
    SETRIGHT(replacement, RIGHT(bp));

    if(parent_node != NULL)
    {
        if(LEFT(parent_node) == bp)
            SETLEFT(parent_node, replacement);
        else
            SETRIGHT(parent_node, replacement);
        return root;
    }
    else
    {
        return replacement;
    }
}
Beispiel #2
0
/*
 * mm_insert - Insert a free block into the Binary Tree and return bp
 */
void *mm_insert(void *root, void* bp)
{
    /* Determine if the tree is empty and initiate all nodes to NULL */

    if(root == NULL)
    {
        SETLEFT(bp, NULL);
        SETRIGHT(bp, NULL);
        return bp;
    }

    else if(GETSIZE(bp) <= GETSIZE(root))
    {
        SETLEFT(root, mm_insert(LEFT(root),bp));
        return root;
    }

    else if(GETSIZE(bp) >  GETSIZE(root))
    {
        SETRIGHT(root, mm_insert(RIGHT(root),bp));
        return root;
    }

    /* If there's an error, return -1 */
    return -1;
}
Beispiel #3
0
/*
 * mm_remove_child - Remove the node from the Binary Tree as long as it has one child
 */
void *mm_remove_child(void *root, void* bp)
{
    void *parent_node = mm_parent(root, bp);
    void *child;

    /* Who is our child? Where is it? */

    if(LEFT(bp) != NULL)
        child = LEFT(bp);
    else
        child = RIGHT(bp);

    if(parent_node != NULL)
    {
        if(LEFT(parent_node) == bp)
            SETLEFT(parent_node, child);
        else
            SETRIGHT(parent_node, child);
        return root;
    }
    else
    {
        return child;
    }
}
Beispiel #4
0
Plane * CMRouter::initPlane(bool rotate90) {
	Tile * bufferTile = TiAlloc();
	TiSetType(bufferTile, Tile::BUFFER);
	TiSetBody(bufferTile, NULL);

	QRectF bufferRect(rotate90 ? m_maxRect90 : m_maxRect);

    TileRect br;
    qrectToTile(bufferRect, br);

	bufferRect.adjust(-bufferRect.width(), -bufferRect.height(), bufferRect.width(), bufferRect.height());
    //DebugDialog::debug("max rect", m_maxRect);
    //DebugDialog::debug("max rect 90", m_maxRect90);


    int l = fasterRealToTile(bufferRect.left());
    int t = fasterRealToTile(bufferRect.top());
    int r = fasterRealToTile(bufferRect.right());
    int b = fasterRealToTile(bufferRect.bottom());
    SETLEFT(bufferTile, l);
    SETYMIN(bufferTile, t);		// TILE is Math Y-axis not computer-graphic Y-axis

	Plane * thePlane = TiNewPlane(bufferTile, br.xmini, br.ymini, br.xmaxi, br.ymaxi);

    SETRIGHT(bufferTile, r);
	SETYMAX(bufferTile, b);		// TILE is Math Y-axis not computer-graphic Y-axis

	// do not use InsertTile here
	TiInsertTile(thePlane, &thePlane->maxRect, NULL, Tile::SPACE); 
    //infoTileRect("insert", thePlane->maxRect);

	return thePlane;
}
Beispiel #5
0
/*
 * mm_remove_node - If a given node has no children, lets remove it.
 */
void *mm_remove_node(void *root, void *bp)
{
    void *parent_node = mm_parent(root, bp);

    if(parent_node != NULL)
    {
        if(LEFT(parent_node) == bp)
            SETLEFT(parent_node, NULL);
        else
            SETRIGHT(parent_node, NULL);
        return root;
    }
    else
    {
        return NULL;
    }
}
Beispiel #6
0
/* Delete node with given key.
   KEY is the key to be deleted, ROOTP is the address of the root of tree,
   COMPAR the comparison function.  */
void *
__tdelete (const void *key, void **vrootp, __compar_fn_t compar)
{
  node p, q, r, retval;
  int cmp;
  node *rootp = (node *) vrootp;
  node root, unchained;
  /* Stack of nodes so we remember the parents without recursion.  It's
     _very_ unlikely that there are paths longer than 40 nodes.  The tree
     would need to have around 250.000 nodes.  */
  int stacksize = 40;
  int sp = 0;
  node **nodestack = alloca (sizeof (node *) * stacksize);

  if (rootp == NULL)
    return NULL;
  p = DEREFNODEPTR(rootp);
  if (p == NULL)
    return NULL;

  CHECK_TREE (p);

  root = DEREFNODEPTR(rootp);
  while ((cmp = (*compar) (key, root->key)) != 0)
    {
      if (sp == stacksize)
	{
	  node **newstack;
	  stacksize += 20;
	  newstack = alloca (sizeof (node *) * stacksize);
	  nodestack = memcpy (newstack, nodestack, sp * sizeof (node *));
	}

      nodestack[sp++] = rootp;
      p = DEREFNODEPTR(rootp);
      if (cmp < 0)
	{
	  rootp = LEFTPTR(p);
	  root = LEFT(p);
	}
      else
	{
	  rootp = RIGHTPTR(p);
	  root = RIGHT(p);
	}
      if (root == NULL)
	return NULL;
    }

  /* This is bogus if the node to be deleted is the root... this routine
     really should return an integer with 0 for success, -1 for failure
     and errno = ESRCH or something.  */
  retval = p;

  /* We don't unchain the node we want to delete. Instead, we overwrite
     it with its successor and unchain the successor.  If there is no
     successor, we really unchain the node to be deleted.  */

  root = DEREFNODEPTR(rootp);

  r = RIGHT(root);
  q = LEFT(root);

  if (q == NULL || r == NULL)
    unchained = root;
  else
    {
      node *parentp = rootp, *up = RIGHTPTR(root);
      node upn;
      for (;;)
	{
	  if (sp == stacksize)
	    {
	      node **newstack;
	      stacksize += 20;
	      newstack = alloca (sizeof (node *) * stacksize);
	      nodestack = memcpy (newstack, nodestack, sp * sizeof (node *));
	    }
	  nodestack[sp++] = parentp;
	  parentp = up;
	  upn = DEREFNODEPTR(up);
	  if (LEFT(upn) == NULL)
	    break;
	  up = LEFTPTR(upn);
	}
      unchained = DEREFNODEPTR(up);
    }

  /* We know that either the left or right successor of UNCHAINED is NULL.
     R becomes the other one, it is chained into the parent of UNCHAINED.  */
  r = LEFT(unchained);
  if (r == NULL)
    r = RIGHT(unchained);
  if (sp == 0)
    SETNODEPTR(rootp,r);
  else
    {
      q = DEREFNODEPTR(nodestack[sp-1]);
      if (unchained == RIGHT(q))
	SETRIGHT(q,r);
      else
	SETLEFT(q,r);
    }

  if (unchained != root)
    root->key = unchained->key;
  if (!RED(unchained))
    {
      /* Now we lost a black edge, which means that the number of black
	 edges on every path is no longer constant.  We must balance the
	 tree.  */
      /* NODESTACK now contains all parents of R.  R is likely to be NULL
	 in the first iteration.  */
      /* NULL nodes are considered black throughout - this is necessary for
	 correctness.  */
      while (sp > 0 && (r == NULL || !RED(r)))
	{
	  node *pp = nodestack[sp - 1];
	  p = DEREFNODEPTR(pp);
	  /* Two symmetric cases.  */
	  if (r == LEFT(p))
	    {
	      /* Q is R's brother, P is R's parent.  The subtree with root
		 R has one black edge less than the subtree with root Q.  */
	      q = RIGHT(p);
	      if (RED(q))
		{
		  /* If Q is red, we know that P is black. We rotate P left
		     so that Q becomes the top node in the tree, with P below
		     it.  P is colored red, Q is colored black.
		     This action does not change the black edge count for any
		     leaf in the tree, but we will be able to recognize one
		     of the following situations, which all require that Q
		     is black.  */
		  SETBLACK(q);
		  SETRED(p);
		  /* Left rotate p.  */
		  SETRIGHT(p,LEFT(q));
		  SETLEFT(q,p);
		  SETNODEPTR(pp,q);
		  /* Make sure pp is right if the case below tries to use
		     it.  */
		  nodestack[sp++] = pp = LEFTPTR(q);
		  q = RIGHT(p);
		}
	      /* We know that Q can't be NULL here.  We also know that Q is
		 black.  */
	      if ((LEFT(q) == NULL || !RED(LEFT(q)))
		  && (RIGHT(q) == NULL || !RED(RIGHT(q))))
		{
		  /* Q has two black successors.  We can simply color Q red.
		     The whole subtree with root P is now missing one black
		     edge.  Note that this action can temporarily make the
		     tree invalid (if P is red).  But we will exit the loop
		     in that case and set P black, which both makes the tree
		     valid and also makes the black edge count come out
		     right.  If P is black, we are at least one step closer
		     to the root and we'll try again the next iteration.  */
		  SETRED(q);
		  r = p;
		}
	      else
		{
		  /* Q is black, one of Q's successors is red.  We can
		     repair the tree with one operation and will exit the
		     loop afterwards.  */
		  if (RIGHT(q) == NULL || !RED(RIGHT(q)))
		    {
		      /* The left one is red.  We perform the same action as
			 in maybe_split_for_insert where two red edges are
			 adjacent but point in different directions:
			 Q's left successor (let's call it Q2) becomes the
			 top of the subtree we are looking at, its parent (Q)
			 and grandparent (P) become its successors. The former
			 successors of Q2 are placed below P and Q.
			 P becomes black, and Q2 gets the color that P had.
			 This changes the black edge count only for node R and
			 its successors.  */
		      node q2 = LEFT(q);
		      if (RED(p))
			SETRED(q2);
		      else
			SETBLACK(q2);
		      SETRIGHT(p,LEFT(q2));
		      SETLEFT(q,RIGHT(q2));
		      SETRIGHT(q2,q);
		      SETLEFT(q2,p);
		      SETNODEPTR(pp,q2);
		      SETBLACK(p);
		    }
		  else
		    {
		      /* It's the right one.  Rotate P left. P becomes black,
			 and Q gets the color that P had.  Q's right successor
			 also becomes black.  This changes the black edge
			 count only for node R and its successors.  */
		      if (RED(p))
			SETRED(q);
		      else
			SETBLACK(q);
		      SETBLACK(p);

		      SETBLACK(RIGHT(q));

		      /* left rotate p */
		      SETRIGHT(p,LEFT(q));
		      SETLEFT(q,p);
		      SETNODEPTR(pp,q);
		    }

		  /* We're done.  */
		  sp = 1;
		  r = NULL;
		}
	    }
	  else
	    {
	      /* Comments: see above.  */
	      q = LEFT(p);
	      if (RED(q))
		{
		  SETBLACK(q);
		  SETRED(p);
		  SETLEFT(p,RIGHT(q));
		  SETRIGHT(q,p);
		  SETNODEPTR(pp,q);
		  nodestack[sp++] = pp = RIGHTPTR(q);
		  q = LEFT(p);
		}
	      if ((RIGHT(q) == NULL || !RED(RIGHT(q)))
		  && (LEFT(q) == NULL || !RED(LEFT(q))))
		{
		  SETRED(q);
		  r = p;
		}
	      else
		{
		  if (LEFT(q) == NULL || !RED(LEFT(q)))
		    {
		      node q2 = RIGHT(q);
		      if (RED(p))
			SETRED(q2);
		      else
			SETBLACK(q2);
		      SETLEFT(p,RIGHT(q2));
		      SETRIGHT(q,LEFT(q2));
		      SETLEFT(q2,q);
		      SETRIGHT(q2,p);
		      SETNODEPTR(pp,q2);
		      SETBLACK(p);
		    }
		  else
		    {
		      if (RED(p))
			SETRED(q);
		      else
			SETBLACK(q);
		      SETBLACK(p);
		      SETBLACK(LEFT(q));
		      SETLEFT(p,RIGHT(q));
		      SETRIGHT(q,p);
		      SETNODEPTR(pp,q);
		    }
		  sp = 1;
		  r = NULL;
		}
	    }
	  --sp;
	}
      if (r != NULL)
	SETBLACK(r);
    }

  free (unchained);
  return retval;
}
Beispiel #7
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;
}
Beispiel #8
0
/* Possibly "split" a node with two red successors, and/or fix up two red
   edges in a row.  ROOTP is a pointer to the lowest node we visited, PARENTP
   and GPARENTP pointers to its parent/grandparent.  P_R and GP_R contain the
   comparison values that determined which way was taken in the tree to reach
   ROOTP.  MODE is 1 if we need not do the split, but must check for two red
   edges between GPARENTP and ROOTP.  */
static void
maybe_split_for_insert (node *rootp, node *parentp, node *gparentp,
			int p_r, int gp_r, int mode)
{
  node root = DEREFNODEPTR(rootp);
  node *rp, *lp;
  node rpn, lpn;
  rp = RIGHTPTR(root);
  rpn = RIGHT(root);
  lp = LEFTPTR(root);
  lpn = LEFT(root);

  /* See if we have to split this node (both successors red).  */
  if (mode == 1
      || ((rpn) != NULL && (lpn) != NULL && RED(rpn) && RED(lpn)))
    {
      /* This node becomes red, its successors black.  */
      SETRED(root);
      if (rpn)
	SETBLACK(rpn);
      if (lpn)
	SETBLACK(lpn);

      /* If the parent of this node is also red, we have to do
	 rotations.  */
      if (parentp != NULL && RED(DEREFNODEPTR(parentp)))
	{
	  node gp = DEREFNODEPTR(gparentp);
	  node p = DEREFNODEPTR(parentp);
	  /* There are two main cases:
	     1. The edge types (left or right) of the two red edges differ.
	     2. Both red edges are of the same type.
	     There exist two symmetries of each case, so there is a total of
	     4 cases.  */
	  if ((p_r > 0) != (gp_r > 0))
	    {
	      /* Put the child at the top of the tree, with its parent
		 and grandparent as successors.  */
	      SETRED(p);
	      SETRED(gp);
	      SETBLACK(root);
	      if (p_r < 0)
		{
		  /* Child is left of parent.  */
		  SETLEFT(p,rpn);
		  SETNODEPTR(rp,p);
		  SETRIGHT(gp,lpn);
		  SETNODEPTR(lp,gp);
		}
	      else
		{
		  /* Child is right of parent.  */
		  SETRIGHT(p,lpn);
		  SETNODEPTR(lp,p);
		  SETLEFT(gp,rpn);
		  SETNODEPTR(rp,gp);
		}
	      SETNODEPTR(gparentp,root);
	    }
	  else
	    {
	      SETNODEPTR(gparentp,p);
	      /* Parent becomes the top of the tree, grandparent and
		 child are its successors.  */
	      SETBLACK(p);
	      SETRED(gp);
	      if (p_r < 0)
		{
		  /* Left edges.  */
		  SETLEFT(gp,RIGHT(p));
		  SETRIGHT(p,gp);
		}
	      else
		{
		  /* Right edges.  */
		  SETRIGHT(gp,LEFT(p));
		  SETLEFT(p,gp);
		}
	    }
	}
    }
}