#include "common.h"#include "localmem.h"#include "rbTree.h"Include dependency graph for rbTree.c:

Go to the source code of this file.
Functions | |
| static struct rbTreeNode * | restructure (struct rbTree *t, int tos, struct rbTreeNode *x, struct rbTreeNode *y, struct rbTreeNode *z) |
| rbTree * | rbTreeNewDetailed (int(*compare)(void *, void *), struct lm *lm, struct rbTreeNode *stack[128]) |
| rbTree * | rbTreeNew (int(*compare)(void *, void *)) |
| void | rbTreeFree (struct rbTree **pTree) |
| void * | rbTreeAdd (struct rbTree *t, void *item) |
| void * | rbTreeFind (struct rbTree *t, void *item) |
| void * | rbTreeRemove (struct rbTree *t, void *item) |
| static void | rTreeDump (struct rbTreeNode *n) |
| void | rbTreeDump (struct rbTree *tree, FILE *f, void(*dumpItem)(void *item, FILE *f)) |
| static void | rTreeTraverseRange (struct rbTreeNode *n) |
| static void | rTreeTraverse (struct rbTreeNode *n) |
| void | rbTreeTraverseRange (struct rbTree *tree, void *minItem, void *maxItem, void(*doItem)(void *item)) |
| void | rbTreeTraverse (struct rbTree *tree, void(*doItem)(void *item)) |
| static void | addRef (void *item) |
| slRef * | rbTreeItemsInRange (struct rbTree *tree, void *minItem, void *maxItem) |
| slRef * | rbTreeItems (struct rbTree *tree) |
| int | rbTreeCmpString (void *a, void *b) |
| int | rbTreeCmpWord (void *a, void *b) |
Variables | |
| static char const | rcsid [] = "$Id: rbTree.c,v 1.10 2007/02/24 15:59:29 kent Exp $" |
| static int | dumpLevel |
| static FILE * | dumpFile |
| static void(*) | dumpIt (void *item, FILE *f) |
| static void(*) | doIt (void *item) |
| static void * | minIt |
| static void * | maxIt |
| static int(*) | compareIt (void *, void *) |
| slRef * | itList |
| static void addRef | ( | void * | item | ) | [static] |
Definition at line 658 of file rbTree.c.
References itList, and refAdd().
Referenced by rbTreeItems(), and rbTreeItemsInRange().
Here is the call graph for this function:

Here is the caller graph for this function:

| 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, lm, rbTree::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:

| static struct rbTreeNode* restructure | ( | struct rbTree * | t, | |
| int | tos, | |||
| struct rbTreeNode * | x, | |||
| struct rbTreeNode * | y, | |||
| struct rbTreeNode * | z | |||
| ) | [static, read] |
Definition at line 15 of file rbTree.c.
References rbTreeNode::left, rbTreeNode::right, rbTree::root, and rbTree::stack.
Referenced by rbTreeAdd(), and rbTreeRemove().
00020 { 00021 struct rbTreeNode *parent, *midNode; 00022 00023 if(y == x->left) 00024 { 00025 if(z == y->left) 00026 { /* in-order: z, y, x */ 00027 midNode = y; 00028 y->left = z; 00029 x->left = y->right; 00030 y->right = x; 00031 } 00032 else 00033 { /* in-order: y, z, x */ 00034 midNode = z; 00035 y->right = z->left; 00036 z->left = y; 00037 x->left = z->right; 00038 z->right = x; 00039 } 00040 } 00041 else 00042 { 00043 if(z == y->left) 00044 { /* in-order: x, z, y */ 00045 midNode = z; 00046 x->right = z->left; 00047 z->left = x; 00048 y->left = z->right; 00049 z->right = y; 00050 } 00051 else 00052 { /* in-order: x, y, z */ 00053 midNode = y; 00054 x->right = y->left; 00055 y->left = x; 00056 y->right = z; 00057 } 00058 } 00059 if(tos != 0) 00060 { 00061 parent = t->stack[tos-1]; 00062 if(x == parent->left) 00063 parent->left = midNode; 00064 else 00065 parent->right = midNode; 00066 } 00067 else 00068 t->root = midNode; 00069 00070 return midNode; 00071 }
Here is the caller graph for this function:

| static void rTreeDump | ( | struct rbTreeNode * | n | ) | [static] |
Definition at line 577 of file rbTree.c.
References rbTreeNode::color, dumpFile, dumpIt, dumpLevel, rbTreeNode::item, rbTreeNode::left, rbTreeRed, rbTreeNode::right, and spaceOut().
Referenced by rbTreeDump().
00579 { 00580 if (n == NULL) 00581 return; 00582 spaceOut(dumpFile, ++dumpLevel * 3); 00583 fprintf(dumpFile, "%c ", (n->color == rbTreeRed ? 'r' : 'b')); 00584 dumpIt(n->item, dumpFile); 00585 fprintf(dumpFile, "\n"); 00586 rTreeDump(n->left); 00587 rTreeDump(n->right); 00588 --dumpLevel; 00589 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void rTreeTraverse | ( | struct rbTreeNode * | n | ) | [static] |
Definition at line 625 of file rbTree.c.
References doIt, rbTreeNode::item, rbTreeNode::left, and rbTreeNode::right.
Referenced by rbTreeTraverse().
00627 { 00628 if (n != NULL) 00629 { 00630 rTreeTraverse(n->left); 00631 doIt(n->item); 00632 rTreeTraverse(n->right); 00633 } 00634 }
Here is the caller graph for this function:

| static void rTreeTraverseRange | ( | struct rbTreeNode * | n | ) | [static] |
Definition at line 609 of file rbTree.c.
References compareIt, doIt, rbTreeNode::item, rbTreeNode::left, and rbTreeNode::right.
Referenced by rbTreeTraverseRange().
00611 { 00612 if (n != NULL) 00613 { 00614 int minCmp = compareIt(n->item, minIt); 00615 int maxCmp = compareIt(n->item, maxIt); 00616 if (minCmp >= 0) 00617 rTreeTraverseRange(n->left); 00618 if (minCmp >= 0 && maxCmp <= 0) 00619 doIt(n->item); 00620 if (maxCmp <= 0) 00621 rTreeTraverseRange(n->right); 00622 } 00623 }
Here is the caller graph for this function:

int(*) compareIt(void *, void *) [static] |
Definition at line 607 of file rbTree.c.
Referenced by rbTreeTraverse(), rbTreeTraverseRange(), and rTreeTraverseRange().
void(*) doIt(void *item) [static] |
Definition at line 605 of file rbTree.c.
Referenced by rbTreeTraverse(), rbTreeTraverseRange(), rTreeTraverse(), and rTreeTraverseRange().
FILE* dumpFile [static] |
void(*) dumpIt(void *item, FILE *f) [static] |
int dumpLevel [static] |
Definition at line 656 of file rbTree.c.
Referenced by addRef(), rbTreeItems(), and rbTreeItemsInRange().
char const rcsid[] = "$Id: rbTree.c,v 1.10 2007/02/24 15:59:29 kent Exp $" [static] |
1.5.2