📄 d_rbtree.h
字号:
x = root;
}
}
x->color = BLACK;
}
template <typename T>
rbtree<T>::rbtree()
{
makeEmptyTree();
}
template <typename T>
rbtree<T>::rbtree(T *first, T *last)
{
// construct an empty tree
makeEmptyTree();
// insert the data into the tree
while (first != last)
insert(*first++);
}
template <typename T>
rbtree<T>::rbtree(const rbtree<T>& obj):
treeSize(obj.treeSize)
{
// call copyTree(), and assign its return value
// to the root
root = copyTree(obj.root);
}
template <typename T>
rbtree<T>::~rbtree()
{
// erase the nodes in the tree
deleteTree(root);
// tree is emtpy
root = NIL;
treeSize = 0;
}
template <typename T>
rbtree<T>& rbtree<T>::operator= (const rbtree<T>& rhs)
{
if (this != &rhs)
{
// erase the tree
deleteTree(root);
// call copyTree(), and assign its return value
// to the root
root = copyTree(rhs.root);
treeSize = rhs.treeSize;
}
return *this;
}
template <typename T>
bool rbtree<T>::empty() const
{
return treeSize == 0;
}
template <typename T>
int rbtree<T>::size() const
{
return treeSize;
}
template <typename T>
rbtree<T>::iterator rbtree<T>::find (const T& item)
{
rbnode<T> *curr;
// search tree for item
curr = findNode(item);
// if item found, return iterator with value current;
// otherwise, return end()
if (curr != NIL)
return iterator(curr, this);
else
return end();
}
template <typename T>
rbtree<T>::const_iterator rbtree<T>::find (const T& item) const
{
rbnode<T> *curr;
// search tree for item
curr = findNode(item);
// if item found, return const_iterator with value current;
// otherwise, return end()
if (curr != NIL)
return const_iterator(curr, this);
else
return end();
}
template <typename T>
pair<rbtree<T>::iterator,bool> rbtree<T>::insert (const T& item)
{
// TOP-DOWN INSERTION
// declare pointers to the current node and its parent
rbnode<T> *curr = root, *parent = NIL, *newNode;
// loop until we find the value in the tree or locate
// the insertion point
while (curr != NIL)
{
if (curr->nodeValue == item)
{
// item is in the tree. return a pair whose first member
// is an iterator pointing at item and whose second member
// is false
return pair<iterator,bool> (iterator(curr,this), false);
}
// a node split is required if both children of curr are RED
if (curr->left->color == RED && curr->right->color == RED)
split4Node(curr);
// move down the tree
parent = curr;
if (item < curr->nodeValue)
curr = curr->left;
else
curr = curr->right;
}
// create the new node
newNode = getRBNode(item, NIL, NIL, parent, RED);
// is item the first node inserted into the tree?
if (parent == NIL)
// item is at the root of a brand new tree.
root = newNode;
else
{
// link the new node into its parent
if (item < parent->nodeValue)
// insert as left child
parent->left = newNode;
else
// insert as right child
parent->right = newNode;
// if the new node's parent is RED, we
// must perform a rotation
if (parent->color == RED)
split4Node(newNode);
}
// the color of the root must be BLACK
root->color = BLACK;
// the tree has one more node
treeSize++;
// we did an insertion. set success to true and return
// an iterator pointing at item
return pair<iterator,bool> (iterator(newNode,this),true);
}
template <typename T>
int rbtree<T>::erase(const T& item)
{
int numberErased = 1;
// search tree for item
rbnode<T> *p = findNode(item);
// if item found, delete the node
if (p != NIL)
erase(iterator(p,this));
else
numberErased = 0;
return numberErased;
}
template <typename T>
void rbtree<T>::erase (iterator pos)
{
// BOTTOM-UP ERASE
// dNodePtr = pointer to node D that is deleted
// pNodePtr = pointer to parent P of node D
// rNodePtr = pointer to node R that replaces D
// spliceOut = pointer to the node that is spliced out of the tree
// childOfSpliceOut = pointer to the child of the node we splice out
rbnode<T> *dNodePtr = pos.nodePtr, *pNodePtr, *rNodePtr,
*spliceOut, *childOfSpliceOut;
// saves color of node that is spliced out
colorType spliceoutColor;
if (dNodePtr == NIL)
throw
referenceError("rbtree erase(): invalid iterator");
// assign pNodePtr the address of P
pNodePtr = dNodePtr->parent;
// If D has a NIL pointer, the
// replacement node is the other child
if (dNodePtr->right == NIL || dNodePtr->left == NIL)
{
if (dNodePtr->right == NIL)
rNodePtr = dNodePtr->left;
else
rNodePtr = dNodePtr->right;
// the parent of R is now the parent of D
// NOTE: rNodePtr may be NIL
rNodePtr->parent = pNodePtr;
// we are splicing dNodePtr out of the tree
spliceOut = dNodePtr;
// save color of dNodePtr
spliceoutColor = spliceOut->color;
// record the child of our spliceout node for possible
// balancing operations
childOfSpliceOut = rNodePtr;
}
// both pointers of dNodePtr are non-NIL.
else
{
// find and unlink replacement node for D.
// starting at the right child of node D,
// find the node whose value is the smallest of all
// nodes whose values are greater than the value in D.
// unlink the node from the tree.
// pOfRNodePtr = pointer to parent of replacement node
rbnode<T> *pOfRNodePtr = dNodePtr;
// first possible replacement is right child of D
rNodePtr = dNodePtr->right;
// descend down left subtree of the right child of D,
// keeping a record of current node and its parent.
// when we stop, we have found the replacement
while(rNodePtr->left != NIL)
{
pOfRNodePtr = rNodePtr;
rNodePtr = rNodePtr->left;
}
// we are splicing rNodePtr out of the tree at its
// current location
spliceOut = rNodePtr;
// save color of the node we will splice out
spliceoutColor = spliceOut->color;
// we will replace dNodPtr by spliceOut. make the color
// of spliceOut the color of dNodePtr
spliceOut->color = dNodePtr->color;
// record the child of our spliceout node for possible
// balancing operations
childOfSpliceOut = rNodePtr->right;
if (pOfRNodePtr == dNodePtr)
{
// right child of deleted node is the replacement.
// assign left subtree of D to left subtree of R
rNodePtr->left = dNodePtr->left;
// assign the parent of D as the parent of R
rNodePtr->parent = pNodePtr;
// assign the left child of D to have parent R
dNodePtr->left->parent = rNodePtr;
// if the right child of rNodePtr is NIL,
// make rNodrPtr the parent of NIL, since any
// required fixup will start with the child
if (rNodePtr->right == NIL)
rNodePtr->right->parent = rNodePtr;
}
else
{
// we moved at least one node down a left branch
// of the right child of D. unlink R from tree by
// assigning its right subtree as the left child of
// the parent of R
pOfRNodePtr->left = rNodePtr->right;
// the parent of the right child of R is the
// parent of R
// NOTE: rNodePtr may be NIL
rNodePtr->right->parent = pOfRNodePtr;
// put replacement node in place of dNodePtr
// assign children of R to be those of D
rNodePtr->left = dNodePtr->left;
rNodePtr->right = dNodePtr->right;
// assign the parent of R to be the parent of D
rNodePtr->parent = pNodePtr;
// assign the parent pointer in the children
// of R to point at R
rNodePtr->left->parent = rNodePtr;
rNodePtr->right->parent = rNodePtr;
}
}
// complete the link to the parent node.
// deleting the root node. assign new root
if (pNodePtr == NIL)
root = rNodePtr;
// attach R to the correct branch of P
else if (dNodePtr->nodeValue < pNodePtr->nodeValue)
pNodePtr->left = rNodePtr;
else
pNodePtr->right = rNodePtr;
// delete the node from memory and decrement tree size
delete dNodePtr;
// fixup the tree if the node spliced out is BLACK
if (spliceoutColor == BLACK)
rbDeleteFixup(childOfSpliceOut);
treeSize--;
}
template <typename T>
void rbtree<T>::erase (rbtree<T>::iterator first,
rbtree<T>::iterator last)
{
if (treeSize == 0)
throw
underflowError("rbtree erase(): tree is empty");
if (first == begin() && last == end())
{
// we are asked to erase the entire tree.
// erase the tree nodes from memory
deleteTree(root);
// tree is emtpy
root = NIL;
treeSize = 0;
}
else
// erase each item in a subrange of the tree
while (first != last)
erase(first++);
}
template <typename T>
rbtree<T>::iterator rbtree<T>::begin()
{
rbnode<T> *curr = root;
// if the tree is not empty, the first node
// inorder is the farthest node left from root
if (curr != NIL)
while (curr->left != NIL)
curr = curr->left;
// build return value using private constructor
return iterator(curr, this);
}
template <typename T>
rbtree<T>::const_iterator rbtree<T>::begin() const
{
const rbnode<T> *curr = root;
// if the tree is not empty, the first node
// inorder is the farthest node left from root
if (curr != NIL)
while (curr->left != NIL)
curr = curr->left;
// build return value using private constructor
return const_iterator(curr, this);
}
template <typename T>
rbtree<T>::iterator rbtree<T>::end()
{
// end indicated by an iterator with NIL stnode pointer
return iterator(NIL, this);
}
template <typename T>
rbtree<T>::const_iterator rbtree<T>::end() const
{
// end indicated by an iterator with NIL stnode pointer
return const_iterator(NIL, this);
}
// recursive inorder scan used to build the shadow tree
template <typename T>
rbnodeShadow *rbtree<T>::buildShadowTree(rbnode<T> *t, int level, int& column) const
{
// pointer to new shadow tree node
rbnodeShadow *newNode = NULL;
// text and ostr used to perform format conversion
char text[80];
ostrstream ostr(text,80);
if (t != NIL)
{
// create the new shadow tree node
newNode = new rbnodeShadow;
// allocate node for left child at next level in tree; attach node
rbnodeShadow *newLeft = buildShadowTree(t->left, level+1, column);
newNode->left = newLeft;
// initialize data members of the new node
if (t->color == RED)
ostr << t->nodeValue << '*' << ends;
else
ostr << t->nodeValue << ends;
newNode->nodeValueStr = text;
newNode->level = level;
newNode->column = column;
// update column to next cell in the table
column++;
// allocate node for right child at next level in tree; attach node
rbnodeShadow *newRight = buildShadowTree(t->right, level+1, column);
newNode->right = newRight;
}
return newNode;
}
template <typename T>
void rbtree<T>::displayTree(int maxCharacters) const
{
string label;
int level = 0, column = 0;
int colWidth = maxCharacters + 1;
//
int currLevel = 0, currCol = 0;
if (treeSize == 0)
return;
// build the shadow tree
rbnodeShadow *shadowRoot = buildShadowTree(root, level, column);
// use during the level order scan of the shadow tree
rbnodeShadow *currNode;
// store siblings of each rbnodeShadow object in a queue so that
// they are visited in order at the next level of the tree
queue<rbnodeShadow *> q;
// insert the root in the queue and set current level to 0
q.push(shadowRoot);
// continue the iterative process until the queue is empty
while(!q.empty())
{
// delete front node from queue and make it the current node
currNode = q.front();
q.pop();
// if level changes, output a newline
if (currNode->level > currLevel)
{
currLevel = currNode->level;
currCol = 0;
cout << endl;
}
// if a left child exists, insert the child in the queue
if(currNode->left != NULL)
q.push(currNode->left);
// if a right child exists, insert the child in the queue
if(currNode->right != NULL)
q.push(currNode->right);
// output formatted node label
if (currNode->column > currCol)
{
cout << setw((currNode->column-currCol)*colWidth) << ' ';
currCol = currNode->column;
}
cout << setw(colWidth) << currNode->nodeValueStr;
currCol++;
}
cout << endl;
// delete the shadow tree
deleteShadowTree(shadowRoot);
}
template <typename T>
void rbtree<T>::deleteShadowTree(rbnodeShadow *t) const
{
// if current root node is not NULL, delete its left subtree,
// its right subtree and then the node itself
if (t != NULL)
{
deleteShadowTree(t->left);
deleteShadowTree(t->right);
delete t;
}
}
#endif // RED_BLACK_TREE_CLASS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -