Professional Documents
Culture Documents
h"
/*********************************************************************
**/
/* FUNCTION: RBTreeCreate */
/**/
/* INPUTS: All the inputs are names of functions. CompFunc takes to
*/
/* void pointers to keys and returns 1 if the first arguement is */
/* "greater than" the second. DestFunc takes a pointer to a key and
*/
/* destroys it in the appropriate manner when the node containing
that */
/* key is deleted. InfoDestFunc is similiar to DestFunc except it */
/* recieves a pointer to the info of a node and destroys it. */
/* PrintFunc recieves a pointer to the key of a node and prints it.
*/
/* PrintInfo recieves a pointer to the info of a node and prints it.
*/
/* If RBTreePrint is never called the print functions don't have to
be */
/* defined and NullFunction can be used. */
/**/
/* OUTPUT: This function returns a pointer to the newly created */
/* red-black tree. */
/**/
/* Modifies Input: none */
/*********************************************************************
**/
newTree=(rb_red_blk_tree*) SafeMalloc(sizeof(rb_red_blk_tree));
newTree->Compare= CompFunc;
newTree->DestroyKey= DestFunc;
newTree->PrintKey= PrintFunc;
newTree->PrintInfo= PrintInfo;
newTree->DestroyInfo= InfoDestFunc;
/*********************************************************************
**/
/* FUNCTION: LeftRotate */
/**/
/* INPUTS: This takes a tree so that it can access the appropriate
*/
/* root and nil pointers, and the node to rotate on. */
/**/
/* OUTPUT: None */
/**/
/* Modifies Input: tree, x */
/**/
/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by
*/
/* Cormen, Leiserson, Rivest (Chapter 14). Basically this
*/
/* makes the parent of x be to the left of x, x the parent
of */
/* its parent before the rotation and fixes other pointers
*/
/* accordingly. */
/*********************************************************************
**/
y=x->right;
x->right=y->left;
if (y->left != nil) y->left->parent=x; /* used to use sentinel here
*/
/* and do an unconditional assignment instead of testing for nil */
y->parent=x->parent;
#ifdef DEBUG_ASSERT
Assert(!tree->nil->red,"nil not red in LeftRotate");
#endif
}
/*********************************************************************
**/
/* FUNCTION: RighttRotate */
/**/
/* INPUTS: This takes a tree so that it can access the appropriate
*/
/* root and nil pointers, and the node to rotate on. */
/**/
/* OUTPUT: None */
/**/
/* Modifies Input?: tree, y */
/**/
/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by
*/
/* Cormen, Leiserson, Rivest (Chapter 14). Basically this
*/
/* makes the parent of x be to the left of x, x the parent
of */
/* its parent before the rotation and fixes other pointers
*/
/* accordingly. */
/*********************************************************************
**/
x=y->left;
y->left=x->right;
#ifdef DEBUG_ASSERT
Assert(!tree->nil->red,"nil not red in RightRotate");
#endif
}
/*********************************************************************
**/
/* FUNCTION: TreeInsertHelp */
/**/
/* INPUTS: tree is the tree to insert into and z is the node to
insert */
/**/
/* OUTPUT: none */
/**/
/* Modifies Input: tree, z */
/**/
/* EFFECTS: Inserts z into the tree as if it were a regular binary
tree */
/* using the algorithm described in
_Introduction_To_Algorithms_ */
/* by Cormen et al. This funciton is only intended to be
called */
/* by the RBTreeInsert function and not by the user */
/*********************************************************************
**/
z->left=z->right=nil;
y=tree->root;
x=tree->root->left;
while( x != nil) {
y=x;
if (1 == tree->Compare(x->key,z->key)) { /* x.key > z.key */
x=x->left;
} else { /* x,key <= z.key */
x=x->right;
}
}
z->parent=y;
if ( (y == tree->root) ||
(1 == tree->Compare(y->key,z->key))) { /* y.key > z.key */
y->left=z;
} else {
y->right=z;
}
#ifdef DEBUG_ASSERT
Assert(!tree->nil->red,"nil not red in TreeInsertHelp");
#endif
}
/* Before calling Insert RBTree the node x should have its key set */
/*********************************************************************
**/
/* FUNCTION: RBTreeInsert */
/**/
/* INPUTS: tree is the red-black tree to insert a node which has a
key */
/* pointed to by key and info pointed to by info. */
/**/
/* OUTPUT: This function returns a pointer to the newly inserted
node */
/* which is guarunteed to be valid until this node is
deleted. */
/* What this means is if another data structure stores this
*/
/* pointer then the tree does not need to be searched when
this */
/* is to be deleted. */
/**/
/* Modifies Input: tree */
/**/
/* EFFECTS: Creates a node node which contains the appropriate key
and */
/* info pointers and inserts it into the tree. */
/*********************************************************************
**/
x=(rb_red_blk_node*) SafeMalloc(sizeof(rb_red_blk_node));
x->key=key;
x->info=info;
TreeInsertHelp(tree,x);
newNode=x;
x->red=1;
while(x->parent->red) { /* use sentinel instead of checking for root
*/
if (x->parent == x->parent->parent->left) {
y=x->parent->parent->right;
if (y->red) {
x->parent->red=0;
y->red=0;
x->parent->parent->red=1;
x=x->parent->parent;
} else {
if (x == x->parent->right) {
x=x->parent;
LeftRotate(tree,x);
}
x->parent->red=0;
x->parent->parent->red=1;
RightRotate(tree,x->parent->parent);
}
} else { /* case for x->parent == x->parent->parent->right */
y=x->parent->parent->left;
if (y->red) {
x->parent->red=0;
y->red=0;
x->parent->parent->red=1;
x=x->parent->parent;
} else {
if (x == x->parent->left) {
x=x->parent;
RightRotate(tree,x);
}
x->parent->red=0;
x->parent->parent->red=1;
LeftRotate(tree,x->parent->parent);
}
}
}
tree->root->left->red=0;
return(newNode);
#ifdef DEBUG_ASSERT
Assert(!tree->nil->red,"nil not red in RBTreeInsert");
Assert(!tree->root->red,"root not red in RBTreeInsert");
#endif
}
/*********************************************************************
**/
/* FUNCTION: TreeSuccessor */
/**/
/* INPUTS: tree is the tree in question, and x is the node we want
the */
/* the successor of. */
/**/
/* OUTPUT: This function returns the successor of x or NULL if no
*/
/* successor exists. */
/**/
/* Modifies Input: none */
/**/
/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
/*********************************************************************
**/
/*********************************************************************
**/
/* FUNCTION: Treepredecessor */
/**/
/* INPUTS: tree is the tree in question, and x is the node we want
the */
/* the predecessor of. */
/**/
/* OUTPUT: This function returns the predecessor of x or NULL if
no */
/* predecessor exists. */
/**/
/* Modifies Input: none */
/**/
/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
/*********************************************************************
**/
/*********************************************************************
**/
/* FUNCTION: InorderTreePrint */
/**/
/* INPUTS: tree is the tree to print and x is the current inorder
node */
/**/
/* OUTPUT: none */
/**/
/* EFFECTS: This function recursively prints the nodes of the tree
*/
/* inorder using the PrintKey and PrintInfo functions. */
/**/
/* Modifies Input: none */
/**/
/* Note: This function should only be called from RBTreePrint */
/*********************************************************************
**/
/*********************************************************************
**/
/* FUNCTION: TreeDestHelper */
/**/
/* INPUTS: tree is the tree to destroy and x is the current node
*/
/**/
/* OUTPUT: none */
/**/
/* EFFECTS: This function recursively destroys the nodes of the
tree */
/* postorder using the DestroyKey and DestroyInfo
functions. */
/**/
/* Modifies Input: tree, x */
/**/
/* Note: This function should only be called by RBTreeDestroy */
/*********************************************************************
**/
/*********************************************************************
**/
/* FUNCTION: RBTreeDestroy */
/**/
/* INPUTS: tree is the tree to destroy */
/**/
/* OUTPUT: none */
/**/
/* EFFECT: Destroys the key and frees memory */
/**/
/* Modifies Input: tree */
/**/
/*********************************************************************
**/
/*********************************************************************
**/
/* FUNCTION: RBTreePrint */
/**/
/* INPUTS: tree is the tree to print */
/**/
/* OUTPUT: none */
/**/
/* EFFECT: This function recursively prints the nodes of the tree
*/
/* inorder using the PrintKey and PrintInfo functions. */
/**/
/* Modifies Input: none */
/**/
/*********************************************************************
**/
/*********************************************************************
**/
/* FUNCTION: RBExactQuery */
/**/
/* INPUTS: tree is the tree to print and q is a pointer to the key
*/
/* we are searching for */
/**/
/* OUTPUT: returns the a node with key equal to q. If there are
*/
/* multiple nodes with key equal to q this function
returns */
/* the one highest in the tree */
/**/
/* Modifies Input: none */
/**/
/*********************************************************************
**/
#ifdef DEBUG_ASSERT
Assert(!tree->nil->red,"nil not black in RBDeleteFixUp");
#endif
}
/*********************************************************************
**/
/* FUNCTION: RBDelete */
/**/
/* INPUTS: tree is the tree to delete node z from */
/**/
/* OUTPUT: none */
/**/
/* EFFECT: Deletes z from tree and frees the key and info of z */
/* using DestoryKey and DestoryInfo. Then calls */
/* RBDeleteFixUp to restore red-black properties */
/**/
/* Modifies Input: tree, z */
/**/
/* The algorithm from this function is from
_Introduction_To_Algorithms_ */
/*********************************************************************
**/
void RBDelete(rb_red_blk_tree* tree, rb_red_blk_node* z){
rb_red_blk_node* y;
rb_red_blk_node* x;
rb_red_blk_node* nil=tree->nil;
rb_red_blk_node* root=tree->root;
#ifdef DEBUG_ASSERT
Assert( (y!=tree->nil),"y is nil in RBDelete\n");
#endif
/* y is the node to splice out and x is its child */
if (!(y->red)) RBDeleteFixUp(tree,x);
tree->DestroyKey(z->key);
tree->DestroyInfo(z->info);
y->left=z->left;
y->right=z->right;
y->parent=z->parent;
y->red=z->red;
z->left->parent=z->right->parent=y;
if (z == z->parent->left) {
z->parent->left=y;
} else {
z->parent->right=y;
}
free(z);
} else {
tree->DestroyKey(y->key);
tree->DestroyInfo(y->info);
if (!(y->red)) RBDeleteFixUp(tree,x);
free(y);
}
#ifdef DEBUG_ASSERT
Assert(!tree->nil->red,"nil not black in RBDelete");
#endif
}
/*********************************************************************
**/
/* FUNCTION: RBDEnumerate */
/**/
/* INPUTS: tree is the tree to look for keys >= low */
/* and <= high with respect to the Compare function */
/**/
/* OUTPUT: stack containing pointers to the nodes between
[low,high] */
/**/
/* Modifies Input: none */
/*********************************************************************
**/
enumResultStack=StackCreate();
while(nil != x) {
if ( 1 == (tree->Compare(x->key,high)) ) { /* x->key > high */
x=x->left;
} else {
lastBest=x;
x=x->right;
}
}
while ( (lastBest != nil) && (1 != tree->Compare(low,lastBest-
>key))) {
StackPush(enumResultStack,lastBest);
lastBest=TreePredecessor(tree,lastBest);
}
return(enumResultStack);
}