/* * 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; } }
/* * 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; }
/* * 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; } }
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; }
/* * 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; } }
/* 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; }
/* 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; }
/* 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); } } } } }