usermode/library/common/red_black_tree.c

00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 
00004 #include "red_black_tree.h"
00005 
00006 /*  as a function to RBTreeCreate when no other suitable function has */
00007 /*  been defined */
00008 
00009 void NullFunction(void * junk) { ; }
00010 
00011 /***********************************************************************/
00012 /*  FUNCTION:  void Assert(int assertion, char* error)  */
00013 
00014 /*  INPUTS: assertion should be a predicated that the programmer */
00015 /*  assumes to be true.  If this assumption is not true the message */
00016 /*  error is printed and the program exits. */
00017 
00018 /*  OUTPUT: None. */
00019 
00020 /*  Modifies input:  none */
00021 
00022 /*  Note:  If DEBUG_ASSERT is not defined then assertions should not */
00023 /*         be in use as they will slow down the code.  Therefore the */
00024 /*         compiler will complain if an assertion is used when */
00025 /*         DEBUG_ASSERT is undefined. */
00026 /***********************************************************************/
00027 
00028 
00029 static void Assert(int assertion, char* error) {
00030   if(!assertion) {
00031     printf("Assertion Failed: %s\n",error);
00032     exit(-1);
00033   }
00034 }
00035 
00036 
00037 /***********************************************************************/
00038 /*  FUNCTION:  RBTreeCreate */
00039 
00040 /*  INPUTS:  All the inputs are names of functions.  CompFunc takes to */
00041 /*  void pointers to keys and returns 1 if the first arguement is */
00042 /*  "greater than" the second.   DestFunc takes a pointer to a key and */
00043 /*  destroys it in the appropriate manner when the node containing that */
00044 /*  key is deleted.  InfoDestFunc is similiar to DestFunc except it */
00045 /*  recieves a pointer to the info of a node and destroys it. */
00046 /*  PrintFunc recieves a pointer to the key of a node and prints it. */
00047 /*  PrintInfo recieves a pointer to the info of a node and prints it. */
00048 /*  If RBTreePrint is never called the print functions don't have to be */
00049 /*  defined and NullFunction can be used.  */
00050 
00051 /*  OUTPUT:  This function returns a pointer to the newly created */
00052 /*  red-black tree. */
00053 
00054 /*  Modifies Input: none */
00055 /***********************************************************************/
00056 
00057 rb_red_blk_tree* RBTreeCreate( int (*CompFunc) (const void*,const void*),
00058                               void (*DestFunc) (void*),
00059                               void (*InfoDestFunc) (void*),
00060                               void (*PrintFunc) (const void*),
00061                               void (*PrintInfo)(void*)) {
00062   rb_red_blk_tree* newTree;
00063   rb_red_blk_node* temp;
00064 
00065   if (!(newTree=(rb_red_blk_tree*) malloc(sizeof(rb_red_blk_tree)))) {
00066      return NULL;
00067   }
00068 
00069   newTree->Compare=  CompFunc;
00070   newTree->DestroyKey= DestFunc;
00071   newTree->PrintKey= PrintFunc;
00072   newTree->PrintInfo= PrintInfo;
00073   newTree->DestroyInfo= InfoDestFunc;
00074 
00075   /*  see the comment in the rb_red_blk_tree structure in red_black_tree.h */
00076   /*  for information on nil and root */
00077   if (!(temp=newTree->nil= (rb_red_blk_node*) malloc(sizeof(rb_red_blk_node)))) {
00078     goto err_alloc_newTree_nil;
00079   }
00080   temp->parent=temp->left=temp->right=temp;
00081   temp->red=0;
00082   temp->key=0;
00083   if(!(temp=newTree->root= (rb_red_blk_node*) malloc(sizeof(rb_red_blk_node)))) {
00084     goto err_alloc_newTree_root;
00085   }
00086   temp->parent=temp->left=temp->right=newTree->nil;
00087   temp->key=0;
00088   temp->red=0;
00089   return(newTree);
00090 
00091 err_alloc_newTree_root:
00092   free(newTree->nil);
00093 err_alloc_newTree_nil:
00094   free(newTree);
00095 }
00096 
00097 /***********************************************************************/
00098 /*  FUNCTION:  LeftRotate */
00099 
00100 /*  INPUTS:  This takes a tree so that it can access the appropriate */
00101 /*           root and nil pointers, and the node to rotate on. */
00102 
00103 /*  OUTPUT:  None */
00104 
00105 /*  Modifies Input: tree, x */
00106 
00107 /*  EFFECTS:  Rotates as described in _Introduction_To_Algorithms by */
00108 /*            Cormen, Leiserson, Rivest (Chapter 14).  Basically this */
00109 /*            makes the parent of x be to the left of x, x the parent of */
00110 /*            its parent before the rotation and fixes other pointers */
00111 /*            accordingly. */
00112 /***********************************************************************/
00113 
00114 void LeftRotate(rb_red_blk_tree* tree, rb_red_blk_node* x) {
00115   rb_red_blk_node* y;
00116   rb_red_blk_node* nil=tree->nil;
00117 
00118   /*  I originally wrote this function to use the sentinel for */
00119   /*  nil to avoid checking for nil.  However this introduces a */
00120   /*  very subtle bug because sometimes this function modifies */
00121   /*  the parent pointer of nil.  This can be a problem if a */
00122   /*  function which calls LeftRotate also uses the nil sentinel */
00123   /*  and expects the nil sentinel's parent pointer to be unchanged */
00124   /*  after calling this function.  For example, when RBDeleteFixUP */
00125   /*  calls LeftRotate it expects the parent pointer of nil to be */
00126   /*  unchanged. */
00127 
00128   y=x->right;
00129   x->right=y->left;
00130 
00131   if (y->left != nil) y->left->parent=x; /* used to use sentinel here */
00132   /* and do an unconditional assignment instead of testing for nil */
00133   
00134   y->parent=x->parent;   
00135 
00136   /* instead of checking if x->parent is the root as in the book, we */
00137   /* count on the root sentinel to implicitly take care of this case */
00138   if( x == x->parent->left) {
00139     x->parent->left=y;
00140   } else {
00141     x->parent->right=y;
00142   }
00143   y->left=x;
00144   x->parent=y;
00145 
00146 #ifdef DEBUG_ASSERT
00147   Assert(!tree->nil->red,"nil not red in LeftRotate");
00148 #endif
00149 }
00150 
00151 
00152 /***********************************************************************/
00153 /*  FUNCTION:  RighttRotate */
00154 
00155 /*  INPUTS:  This takes a tree so that it can access the appropriate */
00156 /*           root and nil pointers, and the node to rotate on. */
00157 
00158 /*  OUTPUT:  None */
00159 
00160 /*  Modifies Input?: tree, y */
00161 
00162 /*  EFFECTS:  Rotates as described in _Introduction_To_Algorithms by */
00163 /*            Cormen, Leiserson, Rivest (Chapter 14).  Basically this */
00164 /*            makes the parent of x be to the left of x, x the parent of */
00165 /*            its parent before the rotation and fixes other pointers */
00166 /*            accordingly. */
00167 /***********************************************************************/
00168 
00169 void RightRotate(rb_red_blk_tree* tree, rb_red_blk_node* y) {
00170   rb_red_blk_node* x;
00171   rb_red_blk_node* nil=tree->nil;
00172 
00173   /*  I originally wrote this function to use the sentinel for */
00174   /*  nil to avoid checking for nil.  However this introduces a */
00175   /*  very subtle bug because sometimes this function modifies */
00176   /*  the parent pointer of nil.  This can be a problem if a */
00177   /*  function which calls LeftRotate also uses the nil sentinel */
00178   /*  and expects the nil sentinel's parent pointer to be unchanged */
00179   /*  after calling this function.  For example, when RBDeleteFixUP */
00180   /*  calls LeftRotate it expects the parent pointer of nil to be */
00181   /*  unchanged. */
00182 
00183   x=y->left;
00184   y->left=x->right;
00185 
00186   if (nil != x->right)  x->right->parent=y; /*used to use sentinel here */
00187   /* and do an unconditional assignment instead of testing for nil */
00188 
00189   /* instead of checking if x->parent is the root as in the book, we */
00190   /* count on the root sentinel to implicitly take care of this case */
00191   x->parent=y->parent;
00192   if( y == y->parent->left) {
00193     y->parent->left=x;
00194   } else {
00195     y->parent->right=x;
00196   }
00197   x->right=y;
00198   y->parent=x;
00199 
00200 #ifdef DEBUG_ASSERT
00201   Assert(!tree->nil->red,"nil not red in RightRotate");
00202 #endif
00203 }
00204 
00205 /***********************************************************************/
00206 /*  FUNCTION:  TreeInsertHelp  */
00207 
00208 /*  INPUTS:  tree is the tree to insert into and z is the node to insert */
00209 
00210 /*  OUTPUT:  none */
00211 
00212 /*  Modifies Input:  tree, z */
00213 
00214 /*  EFFECTS:  Inserts z into the tree as if it were a regular binary tree */
00215 /*            using the algorithm described in _Introduction_To_Algorithms_ */
00216 /*            by Cormen et al.  This funciton is only intended to be called */
00217 /*            by the RBTreeInsert function and not by the user */
00218 /***********************************************************************/
00219 
00220 void TreeInsertHelp(rb_red_blk_tree* tree, rb_red_blk_node* z) {
00221   /*  This function should only be called by InsertRBTree (see above) */
00222   rb_red_blk_node* x;
00223   rb_red_blk_node* y;
00224   rb_red_blk_node* nil=tree->nil;
00225   
00226   z->left=z->right=nil;
00227   y=tree->root;
00228   x=tree->root->left;
00229   while( x != nil) {
00230     y=x;
00231     if (1 == tree->Compare(x->key,z->key)) { /* x.key > z.key */
00232       x=x->left;
00233     } else { /* x,key <= z.key */
00234       x=x->right;
00235     }
00236   }
00237   z->parent=y;
00238   if ( (y == tree->root) ||
00239        (1 == tree->Compare(y->key,z->key))) { /* y.key > z.key */
00240     y->left=z;
00241   } else {
00242     y->right=z;
00243   }
00244 
00245 #ifdef DEBUG_ASSERT
00246   Assert(!tree->nil->red,"nil not red in TreeInsertHelp");
00247 #endif
00248 }
00249 
00250 /*  Before calling Insert RBTree the node x should have its key set */
00251 
00252 /***********************************************************************/
00253 /*  FUNCTION:  RBTreeInsert */
00254 
00255 /*  INPUTS:  tree is the red-black tree to insert a node which has a key */
00256 /*           pointed to by key and info pointed to by info.  */
00257 
00258 /*  OUTPUT:  This function returns a pointer to the newly inserted node */
00259 /*           which is guarunteed to be valid until this node is deleted. */
00260 /*           What this means is if another data structure stores this */
00261 /*           pointer then the tree does not need to be searched when this */
00262 /*           is to be deleted. */
00263 
00264 /*  Modifies Input: tree */
00265 
00266 /*  EFFECTS:  Creates a node node which contains the appropriate key and */
00267 /*            info pointers and inserts it into the tree. */
00268 /***********************************************************************/
00269 
00270 rb_red_blk_node * RBTreeInsert(rb_red_blk_tree* tree, void* key, void* info) {
00271   rb_red_blk_node * y;
00272   rb_red_blk_node * x;
00273   rb_red_blk_node * newNode;
00274 
00275   if (!(x=(rb_red_blk_node*) malloc(sizeof(rb_red_blk_node)))) {
00276     return NULL;
00277   }
00278   x->key=key;
00279   x->info=info;
00280 
00281   TreeInsertHelp(tree,x);
00282   newNode=x;
00283   x->red=1;
00284   while(x->parent->red) { /* use sentinel instead of checking for root */
00285     if (x->parent == x->parent->parent->left) {
00286       y=x->parent->parent->right;
00287       if (y->red) {
00288         x->parent->red=0;
00289         y->red=0;
00290         x->parent->parent->red=1;
00291         x=x->parent->parent;
00292       } else {
00293         if (x == x->parent->right) {
00294           x=x->parent;
00295           LeftRotate(tree,x);
00296         }
00297         x->parent->red=0;
00298         x->parent->parent->red=1;
00299         RightRotate(tree,x->parent->parent);
00300       } 
00301     } else { /* case for x->parent == x->parent->parent->right */
00302       y=x->parent->parent->left;
00303       if (y->red) {
00304         x->parent->red=0;
00305         y->red=0;
00306         x->parent->parent->red=1;
00307         x=x->parent->parent;
00308       } else {
00309         if (x == x->parent->left) {
00310           x=x->parent;
00311           RightRotate(tree,x);
00312         }
00313         x->parent->red=0;
00314         x->parent->parent->red=1;
00315         LeftRotate(tree,x->parent->parent);
00316       } 
00317     }
00318   }
00319   tree->root->left->red=0;
00320   return(newNode);
00321 
00322 #ifdef DEBUG_ASSERT
00323   Assert(!tree->nil->red,"nil not red in RBTreeInsert");
00324   Assert(!tree->root->red,"root not red in RBTreeInsert");
00325 #endif
00326 }
00327 
00328 /***********************************************************************/
00329 /*  FUNCTION:  TreeSuccessor  */
00330 
00331 /*    INPUTS:  tree is the tree in question, and x is the node we want the */
00332 /*             the successor of. */
00333 
00334 /*    OUTPUT:  This function returns the successor of x or NULL if no */
00335 /*             successor exists. */
00336 
00337 /*    Modifies Input: none */
00338 
00339 /*    Note:  uses the algorithm in _Introduction_To_Algorithms_ */
00340 /***********************************************************************/
00341   
00342 rb_red_blk_node* TreeSuccessor(rb_red_blk_tree* tree,rb_red_blk_node* x) { 
00343   rb_red_blk_node* y;
00344   rb_red_blk_node* nil=tree->nil;
00345   rb_red_blk_node* root=tree->root;
00346 
00347   if (nil != (y = x->right)) { /* assignment to y is intentional */
00348     while(y->left != nil) { /* returns the minium of the right subtree of x */
00349       y=y->left;
00350     }
00351     return(y);
00352   } else {
00353     y=x->parent;
00354     while(x == y->right) { /* sentinel used instead of checking for nil */
00355       x=y;
00356       y=y->parent;
00357     }
00358     if (y == root) return(nil);
00359     return(y);
00360   }
00361 }
00362 
00363 /***********************************************************************/
00364 /*  FUNCTION:  Treepredecessor  */
00365 
00366 /*    INPUTS:  tree is the tree in question, and x is the node we want the */
00367 /*             the predecessor of. */
00368 
00369 /*    OUTPUT:  This function returns the predecessor of x or NULL if no */
00370 /*             predecessor exists. */
00371 
00372 /*    Modifies Input: none */
00373 
00374 /*    Note:  uses the algorithm in _Introduction_To_Algorithms_ */
00375 /***********************************************************************/
00376 
00377 rb_red_blk_node* TreePredecessor(rb_red_blk_tree* tree, rb_red_blk_node* x) {
00378   rb_red_blk_node* y;
00379   rb_red_blk_node* nil=tree->nil;
00380   rb_red_blk_node* root=tree->root;
00381 
00382   if (nil != (y = x->left)) { /* assignment to y is intentional */
00383     while(y->right != nil) { /* returns the maximum of the left subtree of x */
00384       y=y->right;
00385     }
00386     return(y);
00387   } else {
00388     y=x->parent;
00389     while(x == y->left) { 
00390       if (y == root) return(nil); 
00391       x=y;
00392       y=y->parent;
00393     }
00394     return(y);
00395   }
00396 }
00397 
00398 /***********************************************************************/
00399 /*  FUNCTION:  InorderTreePrint */
00400 
00401 /*    INPUTS:  tree is the tree to print and x is the current inorder node */
00402 
00403 /*    OUTPUT:  none  */
00404 
00405 /*    EFFECTS:  This function recursively prints the nodes of the tree */
00406 /*              inorder using the PrintKey and PrintInfo functions. */
00407 
00408 /*    Modifies Input: none */
00409 
00410 /*    Note:    This function should only be called from RBTreePrint */
00411 /***********************************************************************/
00412 
00413 void InorderTreePrint(rb_red_blk_tree* tree, rb_red_blk_node* x) {
00414   rb_red_blk_node* nil=tree->nil;
00415   rb_red_blk_node* root=tree->root;
00416   if (x != tree->nil) {
00417     InorderTreePrint(tree,x->left);
00418     printf("info=");
00419     if (tree->PrintInfo) tree->PrintInfo(x->info);
00420     printf("  key="); 
00421         if (tree->PrintKey) {
00422       tree->PrintKey(x->key);
00423         }   
00424     printf("  l->key=");
00425     if( x->left == nil) printf("NULL"); else {
00426           if (tree->PrintKey) tree->PrintKey(x->left->key);     
00427         }  
00428     printf("  r->key=");
00429     if( x->right == nil) printf("NULL"); else {
00430           if (tree->PrintKey) tree->PrintKey(x->right->key);    
00431     }
00432     printf("  p->key=");
00433     if( x->parent == root) printf("NULL"); else {
00434           if (tree->PrintKey) tree->PrintKey(x->parent->key);   
00435     }
00436     printf("  red=%i\n",x->red);
00437     InorderTreePrint(tree,x->right);
00438   }
00439 }
00440 
00441 
00442 /***********************************************************************/
00443 /*  FUNCTION:  TreeDestHelper */
00444 
00445 /*    INPUTS:  tree is the tree to destroy and x is the current node */
00446 
00447 /*    OUTPUT:  none  */
00448 
00449 /*    EFFECTS:  This function recursively destroys the nodes of the tree */
00450 /*              postorder using the DestroyKey and DestroyInfo functions. */
00451 
00452 /*    Modifies Input: tree, x */
00453 
00454 /*    Note:    This function should only be called by RBTreeDestroy */
00455 /***********************************************************************/
00456 
00457 void TreeDestHelper(rb_red_blk_tree* tree, rb_red_blk_node* x) {
00458   rb_red_blk_node* nil=tree->nil;
00459   if (x != nil) {
00460     TreeDestHelper(tree,x->left);
00461     TreeDestHelper(tree,x->right);
00462     tree->DestroyKey(x->key);
00463     tree->DestroyInfo(x->info);
00464     free(x);
00465   }
00466 }
00467 
00468 
00469 /***********************************************************************/
00470 /*  FUNCTION:  RBTreeDestroy */
00471 
00472 /*    INPUTS:  tree is the tree to destroy */
00473 
00474 /*    OUTPUT:  none */
00475 
00476 /*    EFFECT:  Destroys the key and frees memory */
00477 
00478 /*    Modifies Input: tree */
00479 
00480 /***********************************************************************/
00481 
00482 void RBTreeDestroy(rb_red_blk_tree* tree) {
00483   TreeDestHelper(tree,tree->root->left);
00484   free(tree->root);
00485   free(tree->nil);
00486   free(tree);
00487 }
00488 
00489 
00490 /***********************************************************************/
00491 /*  FUNCTION:  RBTreePrint */
00492 
00493 /*    INPUTS:  tree is the tree to print */
00494 
00495 /*    OUTPUT:  none */
00496 
00497 /*    EFFECT:  This function recursively prints the nodes of the tree */
00498 /*             inorder using the PrintKey and PrintInfo functions. */
00499 
00500 /*    Modifies Input: none */
00501 
00502 /***********************************************************************/
00503 
00504 void RBTreePrint(rb_red_blk_tree* tree) {
00505   InorderTreePrint(tree,tree->root->left);
00506 }
00507 
00508 
00509 /***********************************************************************/
00510 /*  FUNCTION:  RBExactQuery */
00511 
00512 /*    INPUTS:  tree is the tree to print and q is a pointer to the key */
00513 /*             we are searching for */
00514 
00515 /*    OUTPUT:  returns the a node with key equal to q.  If there are */
00516 /*             multiple nodes with key equal to q this function returns */
00517 /*             the one highest in the tree */
00518 
00519 /*    Modifies Input: none */
00520 
00521 /***********************************************************************/
00522   
00523 rb_red_blk_node* RBExactQuery(rb_red_blk_tree* tree, void* q) {
00524   rb_red_blk_node* x=tree->root->left;
00525   rb_red_blk_node* nil=tree->nil;
00526   int compVal;
00527   if (x == nil) return(0);
00528   compVal=tree->Compare(x->key,(int*) q);
00529   while(0 != compVal) {/*assignemnt*/
00530     if (1 == compVal) { /* x->key > q */
00531       x=x->left;
00532     } else {
00533       x=x->right;
00534     }
00535     if ( x == nil) return(0);
00536     compVal=tree->Compare(x->key,(int*) q);
00537   }
00538   return(x);
00539 }
00540 
00541 /***********************************************************************/
00542 /*  FUNCTION:  RBQueryLargestSmaller */
00543 
00544 /*    INPUTS:  tree is the tree to print and q is a pointer to the key */
00545 /*             we are searching for */
00546 
00547 /*    OUTPUT:  returns the a node with the largest key which is smaller than q.  
00548 /**/
00549 /*    Modifies Input: none */
00550 
00551 /***********************************************************************/
00552   
00553 rb_red_blk_node* RBQueryLargestSmaller(rb_red_blk_tree* tree, void* q) {
00554   rb_red_blk_node* x=tree->root->left;
00555   rb_red_blk_node* nil=tree->nil;
00556   int compVal;
00557   if (x == nil) return(0);
00558   compVal=tree->Compare(x->key,(int*) q);
00559   while(0 != compVal) {/*assignemnt*/
00560     if (1 == compVal) { /* x->key > q */
00561       x=x->left;
00562     } else {
00563       x=x->right;
00564     }
00565     if ( x == nil) return(0);
00566     compVal=tree->Compare(x->key,(int*) q);
00567   }
00568   return(x);
00569 }
00570 
00571 
00572 
00573 /***********************************************************************/
00574 /*  FUNCTION:  RBDeleteFixUp */
00575 
00576 /*    INPUTS:  tree is the tree to fix and x is the child of the spliced */
00577 /*             out node in RBTreeDelete. */
00578 
00579 /*    OUTPUT:  none */
00580 
00581 /*    EFFECT:  Performs rotations and changes colors to restore red-black */
00582 /*             properties after a node is deleted */
00583 
00584 /*    Modifies Input: tree, x */
00585 
00586 /*    The algorithm from this function is from _Introduction_To_Algorithms_ */
00587 /***********************************************************************/
00588 
00589 void RBDeleteFixUp(rb_red_blk_tree* tree, rb_red_blk_node* x) {
00590   rb_red_blk_node* root=tree->root->left;
00591   rb_red_blk_node* w;
00592 
00593   while( (!x->red) && (root != x)) {
00594     if (x == x->parent->left) {
00595       w=x->parent->right;
00596       if (w->red) {
00597         w->red=0;
00598         x->parent->red=1;
00599         LeftRotate(tree,x->parent);
00600         w=x->parent->right;
00601       }
00602       if ( (!w->right->red) && (!w->left->red) ) { 
00603         w->red=1;
00604         x=x->parent;
00605       } else {
00606         if (!w->right->red) {
00607           w->left->red=0;
00608           w->red=1;
00609           RightRotate(tree,w);
00610           w=x->parent->right;
00611         }
00612         w->red=x->parent->red;
00613         x->parent->red=0;
00614         w->right->red=0;
00615         LeftRotate(tree,x->parent);
00616         x=root; /* this is to exit while loop */
00617       }
00618     } else { /* the code below is has left and right switched from above */
00619       w=x->parent->left;
00620       if (w->red) {
00621         w->red=0;
00622         x->parent->red=1;
00623         RightRotate(tree,x->parent);
00624         w=x->parent->left;
00625       }
00626       if ( (!w->right->red) && (!w->left->red) ) { 
00627         w->red=1;
00628         x=x->parent;
00629       } else {
00630         if (!w->left->red) {
00631           w->right->red=0;
00632           w->red=1;
00633           LeftRotate(tree,w);
00634           w=x->parent->left;
00635         }
00636         w->red=x->parent->red;
00637         x->parent->red=0;
00638         w->left->red=0;
00639         RightRotate(tree,x->parent);
00640         x=root; /* this is to exit while loop */
00641       }
00642     }
00643   }
00644   x->red=0;
00645 
00646 #ifdef DEBUG_ASSERT
00647   Assert(!tree->nil->red,"nil not black in RBDeleteFixUp");
00648 #endif
00649 }
00650 
00651 
00652 /***********************************************************************/
00653 /*  FUNCTION:  RBDelete */
00654 
00655 /*    INPUTS:  tree is the tree to delete node z from */
00656 
00657 /*    OUTPUT:  none */
00658 
00659 /*    EFFECT:  Deletes z from tree and frees the key and info of z */
00660 /*             using DestoryKey and DestoryInfo.  Then calls */
00661 /*             RBDeleteFixUp to restore red-black properties */
00662 
00663 /*    Modifies Input: tree, z */
00664 
00665 /*    The algorithm from this function is from _Introduction_To_Algorithms_ */
00666 /***********************************************************************/
00667 
00668 void RBDelete(rb_red_blk_tree* tree, rb_red_blk_node* z){
00669   rb_red_blk_node* y;
00670   rb_red_blk_node* x;
00671   rb_red_blk_node* nil=tree->nil;
00672   rb_red_blk_node* root=tree->root;
00673 
00674   y= ((z->left == nil) || (z->right == nil)) ? z : TreeSuccessor(tree,z);
00675   x= (y->left == nil) ? y->right : y->left;
00676   if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */
00677     root->left=x;
00678   } else {
00679     if (y == y->parent->left) {
00680       y->parent->left=x;
00681     } else {
00682       y->parent->right=x;
00683     }
00684   }
00685   if (y != z) { /* y should not be nil in this case */
00686 
00687 #ifdef DEBUG_ASSERT
00688     Assert( (y!=tree->nil),"y is nil in RBDelete\n");
00689 #endif
00690     /* y is the node to splice out and x is its child */
00691 
00692     if (!(y->red)) RBDeleteFixUp(tree,x);
00693   
00694     tree->DestroyKey(z->key);
00695     tree->DestroyInfo(z->info);
00696     y->left=z->left;
00697     y->right=z->right;
00698     y->parent=z->parent;
00699     y->red=z->red;
00700     z->left->parent=z->right->parent=y;
00701     if (z == z->parent->left) {
00702       z->parent->left=y; 
00703     } else {
00704       z->parent->right=y;
00705     }
00706     free(z); 
00707   } else {
00708     tree->DestroyKey(y->key);
00709     tree->DestroyInfo(y->info);
00710     if (!(y->red)) RBDeleteFixUp(tree,x);
00711     free(y);
00712   }
00713   
00714 #ifdef DEBUG_ASSERT
00715   Assert(!tree->nil->red,"nil not black in RBDelete");
00716 #endif
00717 }
00718 
00719 
00720 /***********************************************************************/
00721 /*  FUNCTION:  RBDEnumerate */
00722 
00723 /*    INPUTS:  tree is the tree to look for keys >= low */
00724 /*             and <= high with respect to the Compare function */
00725 
00726 /*    OUTPUT:  stack containing pointers to the nodes between [low,high] */
00727 
00728 /*    Modifies Input: none */
00729 /***********************************************************************/
00730 
00731 stk_stack* RBEnumerate(rb_red_blk_tree* tree, void* low, void* high) {
00732   stk_stack* enumResultStack;
00733   rb_red_blk_node* nil=tree->nil;
00734   rb_red_blk_node* x=tree->root->left;
00735   rb_red_blk_node* lastBest=nil;
00736 
00737   enumResultStack=StackCreate();
00738   while(nil != x) {
00739     if ( 1 == (tree->Compare(x->key,high)) ) { /* x->key > high */
00740       x=x->left;
00741     } else {
00742       lastBest=x;
00743       x=x->right;
00744     }
00745   }
00746   while ( (lastBest != nil) && (1 != tree->Compare(low,lastBest->key))) {
00747     StackPush(enumResultStack,lastBest);
00748     lastBest=TreePredecessor(tree,lastBest);
00749   }
00750   return(enumResultStack);
00751 }

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7