inc/rbTree.h File Reference

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

rbTreerbTreeNew (int(*compare)(void *, void *))
void rbTreeFree (struct rbTree **pTree)
rbTreerbTreeNewDetailed (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))
slRefrbTreeItemsInRange (struct rbTree *tree, void *minItem, void *maxItem)
void rbTreeTraverse (struct rbTree *tree, void(*doItem)(void *item))
slRefrbTreeItems (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)


Enumeration Type Documentation

enum rbTreeColor

Enumerator:
rbTreeRed 
rbTreeBlack 

Definition at line 10 of file rbTree.h.


Function Documentation

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 
)

Definition at line 683 of file rbTree.c.

00685 {
00686 return strcmp(a, b);
00687 }

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 
)

Definition at line 591 of file rbTree.c.

References dumpFile, dumpIt, dumpLevel, rbTree::root, and rTreeDump().

00594 {
00595 dumpFile = f;
00596 dumpLevel = 0;
00597 dumpIt = dumpItem;
00598 fprintf(f, "rbTreeDump\n");
00599 rTreeDump(tree->root);
00600 }

Here is the call graph for this function:

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 109 of file rbTree.c.

References freez(), rbTree::lm, lmCleanup(), and pTree().

00111 {
00112 struct rbTree *tree = *pTree;
00113 if (tree != NULL)
00114     {
00115     lmCleanup(&tree->lm);
00116     freez(pTree);
00117     }
00118 }

Here is the call graph for this function:

struct slRef* rbTreeItems ( struct rbTree tree  )  [read]

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:

struct slRef* rbTreeItemsInRange ( struct rbTree tree,
void *  minItem,
void *  maxItem 
) [read]

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:


Generated on Tue Dec 25 19:14:06 2007 for blat by  doxygen 1.5.2