This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Data Structures | |
| struct | rbTreeNode |
| struct | rbTree |
Enumerations | |
| enum | rbTreeColor { rbTreeRed, rbTreeBlack } |
Functions | |
| rbTree * | rbTreeNew (int(*compare)(void *, void *)) |
| void | rbTreeFree (struct rbTree **pTree) |
| rbTree * | rbTreeNewDetailed (int(*compare)(void *, void *), struct lm *lm, struct rbTreeNode *stack[128]) |
| void * | rbTreeAdd (struct rbTree *t, void *item) |
| void * | rbTreeFind (struct rbTree *t, void *item) |
| void * | rbTreeRemove (struct rbTree *t, void *item) |
| void | rbTreeTraverseRange (struct rbTree *tree, void *minItem, void *maxItem, void(*doItem)(void *item)) |
| slRef * | rbTreeItemsInRange (struct rbTree *tree, void *minItem, void *maxItem) |
| void | rbTreeTraverse (struct rbTree *tree, void(*doItem)(void *item)) |
| slRef * | rbTreeItems (struct rbTree *tree) |
| void | rbTreeDump (struct rbTree *tree, FILE *f, void(*dumpItem)(void *item, FILE *f)) |
| int | rbTreeCmpString (void *a, void *b) |
| int | rbTreeCmpWord (void *a, void *b) |
| enum rbTreeColor |
| void* rbTreeAdd | ( | struct rbTree * | t, | |
| void * | item | |||
| ) |
Definition at line 121 of file rbTree.c.
References rbTreeNode::color, rbTree::compare, rbTree::freeList, rbTreeNode::item, rbTreeNode::left, rbTree::lm, lmAllocVar, rbTree::n, rbTreeBlack, rbTreeRed, restructure(), rbTreeNode::right, rbTree::root, and rbTree::stack.
Referenced by rangeTreeAdd().
00128 { 00129 struct rbTreeNode *x, *p, *q, *m, **attachX; 00130 int (* compare)(void *, void *); 00131 int cmpResult; 00132 rbTreeColor col; 00133 struct rbTreeNode **stack = NULL; 00134 int tos; 00135 00136 tos = 0; 00137 if((p = t->root) != NULL) 00138 { 00139 compare = t->compare; 00140 stack = t->stack; 00141 00142 /* Repeatedly explore either the left branch or the right branch 00143 * depending on the value of the key, until an empty branch is chosen. 00144 */ 00145 for(;;) 00146 { 00147 stack[tos++] = p; 00148 cmpResult = compare(item, p->item); 00149 if(cmpResult < 0) 00150 { 00151 p = p->left; 00152 if(!p) 00153 { 00154 p = stack[--tos]; 00155 attachX = &p->left; 00156 break; 00157 } 00158 } 00159 else if(cmpResult > 0) 00160 { 00161 p = p->right; 00162 if(!p) 00163 { 00164 p = stack[--tos]; 00165 attachX = &p->right; 00166 break; 00167 } 00168 } 00169 else 00170 { 00171 return p->item; 00172 } 00173 } 00174 col = rbTreeRed; 00175 } 00176 else 00177 { 00178 attachX = &t->root; 00179 col = rbTreeBlack; 00180 } 00181 00182 /* Allocate new node and place it in tree. */ 00183 if ((x = t->freeList) != NULL) 00184 t->freeList = x->right; 00185 else 00186 lmAllocVar(t->lm, x); 00187 x->left = x->right = NULL; 00188 x->item = item; 00189 x->color = col; 00190 *attachX = x; 00191 t->n++; 00192 00193 /* Restructuring or recolouring will be needed if node x and its parent, p, 00194 * are both red. 00195 */ 00196 if(tos > 0) 00197 { 00198 while(p->color == rbTreeRed) 00199 { /* Double red problem. */ 00200 00201 /* Obtain a pointer to p's parent, m, and sibling, q. */ 00202 m = stack[--tos]; 00203 q = p == m->left ? m->right : m->left; 00204 00205 /* Determine whether restructuring or recolouring is needed. */ 00206 if(!q || q->color == rbTreeBlack) 00207 { 00208 /* Sibling is black. ==> Perform restructuring. */ 00209 00210 /* Restructure according to the left to right order, of nodes 00211 * m, p, and x. 00212 */ 00213 m = restructure(t, tos, m, p, x); 00214 m->color = rbTreeBlack; 00215 m->left->color = m->right->color = rbTreeRed; 00216 00217 /* Restructuring eliminates the double red problem. */ 00218 break; 00219 } 00220 /* else just need to flip color */ 00221 00222 /* Sibling is also red. ==> Perform recolouring. */ 00223 p->color = rbTreeBlack; 00224 q->color = rbTreeBlack; 00225 00226 if(tos == 0) break; /* The root node always remains black. */ 00227 00228 m->color = rbTreeRed; 00229 00230 /* Continue, checking colouring higher up. */ 00231 x = m; 00232 p = stack[--tos]; 00233 } 00234 } 00235 00236 return NULL; 00237 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int rbTreeCmpString | ( | void * | a, | |
| void * | b | |||
| ) |
| int rbTreeCmpWord | ( | void * | a, | |
| void * | b | |||
| ) |
Definition at line 689 of file rbTree.c.
References differentWord().
00691 { 00692 return differentWord(a,b); 00693 }
Here is the call graph for this function:

| void rbTreeDump | ( | struct rbTree * | tree, | |
| FILE * | f, | |||
| void(*)(void *item, FILE *f) | dumpItem | |||
| ) |
| void* rbTreeFind | ( | struct rbTree * | t, | |
| void * | item | |||
| ) |
Definition at line 240 of file rbTree.c.
References rbTree::compare, rbTreeNode::item, rbTreeNode::left, rbTreeNode::right, and rbTree::root.
Referenced by rangeTreeFindEnclosing(), and rangeTreeOverlaps().
00245 { 00246 struct rbTreeNode *p, *nextP; 00247 int (*compare)(void *, void *) = t->compare; 00248 int cmpResult; 00249 00250 /* Repeatedly explore either the left or right branch, depending on the 00251 * value of the key, until the correct item is found. */ 00252 for (p = t->root; p != NULL; p = nextP) 00253 { 00254 cmpResult = compare(item, p->item); 00255 if(cmpResult < 0) 00256 nextP = p->left; 00257 else if(cmpResult > 0) 00258 nextP = p->right; 00259 else 00260 return p->item; 00261 } 00262 return NULL; 00263 }
Here is the caller graph for this function:

| void rbTreeFree | ( | struct rbTree ** | pTree | ) |
Definition at line 674 of file rbTree.c.
References addRef(), itList, rbTreeTraverse(), and slReverse().
00676 { 00677 itList = NULL; 00678 rbTreeTraverse(tree, addRef); 00679 slReverse(&itList); 00680 return itList; 00681 }
Here is the call graph for this function:

Definition at line 664 of file rbTree.c.
References addRef(), itList, rbTreeTraverseRange(), and slReverse().
00667 { 00668 itList = NULL; 00669 rbTreeTraverseRange(tree, minItem, maxItem, addRef); 00670 slReverse(&itList); 00671 return itList; 00672 }
Here is the call graph for this function:

| struct rbTree* rbTreeNew | ( | int(*)(void *, void *) | compare | ) | [read] |
Definition at line 89 of file rbTree.c.
References lm, lmAlloc(), lmInit(), and rbTreeNewDetailed().
Referenced by rangeTreeNew().
00094 { 00095 /* The stack keeps us from having to keep explicit 00096 * parent, grandparent, greatgrandparent variables. 00097 * It needs to be big enough for the maximum depth 00098 * of tree. Since the whole point of rb trees is 00099 * that they are self-balancing, this is not all 00100 * that deep, just 2*log2(N). Therefore a stack of 00101 * 128 is good for up to 2^64 items in stack, which 00102 * should keep us for the next couple of decades... */ 00103 struct lm *lm = lmInit(0); 00104 struct rbTreeNode **stack = lmAlloc(lm, 128 * sizeof(stack[0])); 00105 return rbTreeNewDetailed(compare, lm, stack); 00106 }
Here is the call graph for this function:

Here is the caller graph for this function:

| struct rbTree* rbTreeNewDetailed | ( | int(*)(void *, void *) | compare, | |
| struct lm * | lm, | |||
| struct rbTreeNode * | stack[128] | |||
| ) | [read] |
Definition at line 73 of file rbTree.c.
References AllocVar, rbTree::compare, rbTree::lm, lm, rbTree::n, rbTree::root, and rbTree::stack.
Referenced by rangeTreeNewDetailed(), and rbTreeNew().
00078 { 00079 struct rbTree *t; 00080 AllocVar(t); 00081 t->root = NULL; 00082 t->compare = compare; 00083 t->lm = lm; 00084 t->stack = stack; 00085 t->n = 0; 00086 return t; 00087 }
Here is the caller graph for this function:

| void* rbTreeRemove | ( | struct rbTree * | t, | |
| void * | item | |||
| ) |
Definition at line 266 of file rbTree.c.
References rbTreeNode::color, rbTree::compare, rbTree::freeList, rbTreeNode::item, rbTreeNode::left, rbTree::n, rbTreeBlack, rbTreeRed, restructure(), rbTreeNode::right, rbTree::root, and rbTree::stack.
Referenced by rangeTreeAdd().
00271 { 00272 struct rbTreeNode *p, *r, *x, *y, *z, *b, *newY; 00273 struct rbTreeNode *m; 00274 rbTreeColor removeCol; 00275 void *returnItem; 00276 int (* compare)(void *, void *); 00277 int cmpResult; 00278 struct rbTreeNode **stack; 00279 int i, tos; 00280 00281 00282 /* Attempt to locate the item to be deleted. */ 00283 if((p = t->root)) 00284 { 00285 compare = t->compare; 00286 stack = t->stack; 00287 tos = 0; 00288 00289 for(;;) 00290 { 00291 stack[tos++] = p; 00292 cmpResult = compare(item, p->item); 00293 if(cmpResult < 0) 00294 p = p->left; 00295 else if(cmpResult > 0) 00296 p = p->right; 00297 else 00298 /* Item found. */ 00299 break; 00300 if(!p) return NULL; 00301 } 00302 } 00303 else 00304 return NULL; 00305 00306 /* p points to the node to be deleted, and is currently on the top of the 00307 * stack. 00308 */ 00309 if(!p->left) 00310 { 00311 tos--; /* Adjust tos to remove p. */ 00312 /* Right child replaces p. */ 00313 if(tos == 0) 00314 { 00315 r = t->root = p->right; 00316 x = y = NULL; 00317 } 00318 else 00319 { 00320 x = stack[--tos]; 00321 if(p == x->left) 00322 { 00323 r = x->left = p->right; 00324 y = x->right; 00325 } 00326 else 00327 { 00328 r = x->right = p->right; 00329 y = x->left; 00330 } 00331 } 00332 removeCol = p->color; 00333 } 00334 else if(!p->right) 00335 { 00336 tos--; /* Adjust tos to remove p. */ 00337 /* Left child replaces p. */ 00338 if(tos == 0) 00339 { 00340 r = t->root = p->left; 00341 x = y = NULL; 00342 } 00343 else 00344 { 00345 x = stack[--tos]; 00346 if(p == x->left) 00347 { 00348 r = x->left = p->left; 00349 y = x->right; 00350 } 00351 else 00352 { 00353 r = x->right = p->left; 00354 y = x->left; 00355 } 00356 } 00357 removeCol = p->color; 00358 } 00359 else 00360 { 00361 /* Save p's stack position. */ 00362 i = tos-1; 00363 00364 /* Minimum child, m, in the right subtree replaces p. */ 00365 m = p->right; 00366 do 00367 { 00368 stack[tos++] = m; 00369 m = m->left; 00370 } while(m); 00371 m = stack[--tos]; 00372 00373 /* Update either the left or right child pointers of p's parent. */ 00374 if(i == 0) 00375 { 00376 t->root = m; 00377 } 00378 else 00379 { 00380 x = stack[i-1]; /* p's parent. */ 00381 if(p == x->left) 00382 { 00383 x->left = m; 00384 } 00385 else 00386 { 00387 x->right = m; 00388 } 00389 } 00390 00391 /* Update the tree part m is removed from, and assign m the child 00392 * pointers of p (only if m is not the right child of p). 00393 */ 00394 stack[i] = m; /* Node m replaces node p on the stack. */ 00395 x = stack[--tos]; 00396 r = m->right; 00397 if(tos != i) 00398 { /* x is equal to the parent of m. */ 00399 y = x->right; 00400 x->left = r; 00401 m->right = p->right; 00402 } 00403 else 00404 { /* m was the right child of p, and x is equal to m. */ 00405 y = p->left; 00406 } 00407 m->left = p->left; 00408 00409 /* We treat node m as the node which has been removed. */ 00410 removeCol = m->color; 00411 m->color = p->color; 00412 } 00413 00414 /* Get return value and reuse the space used by node p. */ 00415 returnItem = p->item; 00416 p->right = t->freeList; 00417 t->freeList = p; 00418 00419 t->n--; 00420 00421 /* The pointers x, y, and r point to nodes which may be involved in 00422 * restructuring and recolouring. 00423 * x - the parent of the removed node. 00424 * y - the sibling of the removed node. 00425 * r - the node which replaced the removed node. 00426 * From the above code, the next entry off the stack will be the parent of 00427 * node x. 00428 */ 00429 00430 /* The number of black nodes on paths to all external nodes (NULL child 00431 * pointers) must remain the same for all paths. Restructuring or 00432 * recolouring of nodes may be necessary to enforce this. 00433 */ 00434 if(removeCol == rbTreeBlack) 00435 { 00436 /* Removal of a black node requires some adjustment. */ 00437 00438 if(!r || r->color == rbTreeBlack) 00439 { 00440 /* A black node replaced the deleted black node. Note that 00441 * external nodes (NULL child pointers) are always black, so 00442 * if r is NULL it is treated as a black node. 00443 */ 00444 00445 /* This causes a double-black problem, since node r would need to 00446 * be coloured double-black in order for the black color on 00447 * paths through r to remain the same as for other paths. 00448 */ 00449 00450 /* If r is the root node, the double-black color is not necessary 00451 * to maintain the color balance. Otherwise, some adjustment of 00452 * nearby nodes is needed in order to eliminate the double-black 00453 * problem. NOTE: x points to the parent of r. 00454 */ 00455 if(x) for(;;) 00456 { 00457 00458 /* There are three adjustment cases: 00459 * 1. r's sibling, y, is black and has a red child, z. 00460 * 2. r's sibling, y, is black and has two black children. 00461 * 3. r's sibling, y, is red. 00462 */ 00463 if(y->color == rbTreeBlack) 00464 { 00465 00466 /* Note the conditional evaluation for assigning z. */ 00467 if(((z = y->left) && z->color == rbTreeRed) || 00468 ((z = y->right) && z->color == rbTreeRed)) 00469 { 00470 /* Case 1: perform a restructuring of nodes x, y, and 00471 * z. 00472 */ 00473 00474 b = restructure(t, tos, x, y, z); 00475 b->color = x->color; 00476 b->left->color = b->right->color = rbTreeBlack; 00477 00478 break; 00479 } 00480 else 00481 { 00482 /* Case 2: recolour node y red. */ 00483 00484 y->color = rbTreeRed; 00485 00486 if(x->color == rbTreeRed) 00487 { 00488 x->color = rbTreeBlack; 00489 break; 00490 } 00491 /* else */ 00492 00493 if(tos == 0) break; /* Root level reached. */ 00494 /* else */ 00495 00496 r = x; 00497 x = stack[--tos]; /* x <- parent of x. */ 00498 y = x->left == r ? x->right : x->left; 00499 } 00500 } 00501 else 00502 { 00503 /* Case 3: Restructure nodes x, y, and z, where: 00504 * - If node y is the left child of x, then z is the left 00505 * child of y. Otherwise z is the right child of y. 00506 */ 00507 if(x->left == y) 00508 { 00509 newY = y->right; 00510 z = y->left; 00511 } 00512 else 00513 { 00514 newY = y->left; 00515 z = y->right; 00516 } 00517 00518 restructure(t, tos, x, y, z); 00519 y->color = rbTreeBlack; 00520 x->color = rbTreeRed; 00521 00522 /* Since x has moved down a place in the tree, and y is the 00523 * new the parent of x, the stack must be adjusted so that 00524 * the parent of x is correctly identified in the next call 00525 * to restructure(). 00526 */ 00527 stack[tos++] = y; 00528 00529 /* After restructuring, node r has a black sibling, newY, 00530 * so either case 1 or case 2 applies. If case 2 applies 00531 * the double-black problem does not reappear. 00532 */ 00533 y = newY; 00534 00535 /* Note the conditional evaluation for assigning z. */ 00536 if(((z = y->left) && z->color == rbTreeRed) || 00537 ((z = y->right) && z->color == rbTreeRed)) 00538 { 00539 /* Case 1: perform a restructuring of nodes x, y, and 00540 * z. 00541 */ 00542 00543 b = restructure(t, tos, x, y, z); 00544 b->color = rbTreeRed; /* Since node x was red. */ 00545 b->left->color = b->right->color = rbTreeBlack; 00546 } 00547 else 00548 { 00549 /* Case 2: recolour node y red. */ 00550 00551 /* Note that node y is black and node x is red. */ 00552 00553 y->color = rbTreeRed; 00554 x->color = rbTreeBlack; 00555 } 00556 00557 break; 00558 } 00559 } 00560 } 00561 else 00562 { 00563 /* A red node replaced the deleted black node. */ 00564 00565 /* In this case we can simply color the red node black. */ 00566 r->color = rbTreeBlack; 00567 } 00568 } 00569 return returnItem; 00570 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void rbTreeTraverse | ( | struct rbTree * | tree, | |
| void(*)(void *item) | doItem | |||
| ) |
Definition at line 648 of file rbTree.c.
References rbTree::compare, compareIt, doIt, rbTree::root, and rTreeTraverse().
Referenced by rangeTreeList(), and rbTreeItems().
00650 { 00651 doIt = doItem; 00652 compareIt = tree->compare; 00653 rTreeTraverse(tree->root); 00654 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void rbTreeTraverseRange | ( | struct rbTree * | tree, | |
| void * | minItem, | |||
| void * | maxItem, | |||
| void(*)(void *item) | doItem | |||
| ) |
Definition at line 636 of file rbTree.c.
References rbTree::compare, compareIt, doIt, rbTree::root, and rTreeTraverseRange().
Referenced by rangeTreeAllOverlapping(), rangeTreeOverlapSize(), and rbTreeItemsInRange().
00640 { 00641 doIt = doItem; 00642 minIt = minItem; 00643 maxIt = maxItem; 00644 compareIt = tree->compare; 00645 rTreeTraverseRange(tree->root); 00646 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.5.2