bintree.h
来自「经典的红黑树算法」· C头文件 代码 · 共 1,118 行 · 第 1/2 页
H
1,118 行
/*=====================================================================
BinTree.h - Binary tree template class
Author: Per Nilsson
Freeware and no copyright on my behalf. However, if you use the
code in some manner I'd appreciate a notification about it
perfnurt@hotmail.com
The Red-Black insertion algorithm is to some extent based upon
the example in
http://www.oopweb.com/Algorithms/Documents/PLDS210/Volume/red_black.html
Classes:
// The node class.
template <class KeyType, class ValueType> class BinTreeNode
// The tree class
template <class KeyType, class ValueType> class BinTree
{
public:
// Regular low->high (++) and high->low (--) iterator
class Iterator
// Top to bottom iterator
class ParentFirstIterator
// Bottom to top iterator
class ParentLastIterator
// Top to bottom, level by level iterator
class ByLevelIterator
}
Requirements:
The KeyType class must support:
1. < and == operations.
2. Copy construction.
The ValueType must support:
1. Copy construction.
2. Assignment operation (=) if BinTreeNode::SetValue is used
Dependencies:
No external dependencies
#define NO_REDBLACK to deactivate the red-black functionality.
Tree will still work, but nothing is done in regards of balancing.
=====================================================================*/
#ifndef _BINTREE_H_
#define _BINTREE_H_
//------------------------------------------------------------
// class BinTreeNode is the element type of the BinTree tree.
//------------------------------------------------------------
template <class KeyType, class ValueType>
class BinTreeNode
{
public:
//------------------------------
// Public Construction
//------------------------------
// Constructor(Key, Value)
BinTreeNode(const KeyType& k, const ValueType& v)
:mKey(k),mValue(v),mLeftChild(0),mRightChild(0),mParent(0)
#ifndef NO_REDBLACK
,mIsRed(true)
#endif
{}
// Destructor
virtual ~BinTreeNode(){}
//------------------------------
// Public Commands
//------------------------------
// Set methods.
// Set*Child also updates the the child's parent attribute.
void SetLeftChild(BinTreeNode* p) { mLeftChild=p; if (p) p->SetParent(this);}
void SetRightChild(BinTreeNode* p) { mRightChild=p;if (p) p->SetParent(this);}
void SetParent(BinTreeNode* p) { mParent=p; }
void SetValue(const ValueType& v) { mValue = v; }
// Note: Deliberately no SetKey, that could easily screw up the tree.
// If a key shall be changed, delete node from tree and insert a new one instead.
#ifndef NO_REDBLACK
void SetRed() { mIsRed = true; }
void SetBlack() { mIsRed = false; }
#endif
//------------------------------
// Public Queries
//------------------------------
// Get methods
BinTreeNode* GetLeftChild() const { return mLeftChild; }
BinTreeNode* GetRightChild() const { return mRightChild; }
BinTreeNode* GetParent() const { return mParent; }
ValueType GetValue() const { return mValue; }
KeyType GetKey() const { return mKey; }
// Some more or less useful queries
bool IsRoot() const { return mParent==0; }
bool IsLeftChild() const { return mParent!=0 && mParent->GetLeftChild()==this; }
bool IsRightChild() const { return mParent!=0 && mParent->GetRightChild()==this; }
bool IsLeaf() const { return mLeftChild==0 && mRightChild==0; }
unsigned int GetLevel() const { if (IsRoot()) return 1; else return GetParent()->GetLevel() + 1; }
#ifndef NO_REDBLACK
bool IsRed() const { return mIsRed; };
bool IsBlack() const { return !mIsRed; };
#endif
private:
//------------------------------
// Disabled Methods
//------------------------------
// Default constructor - deliberately not implemented
BinTreeNode();
//------------------------------
// Private Members
//------------------------------
BinTreeNode* mLeftChild;
BinTreeNode* mRightChild;
BinTreeNode* mParent;
KeyType mKey;
ValueType mValue;
#ifndef NO_REDBLACK
bool mIsRed;
#endif
};
//------------------------------------------------------------
// class BinTree. Holder of the tree structure.
//------------------------------------------------------------
template <class KeyType, class ValueType>
class BinTree
{
public:
//------------------------------
// Public Definitions
//------------------------------
typedef BinTreeNode<KeyType,ValueType> Node;
//------------------------------
// Public Classes
//------------------------------
//--------------------------------------------------------
// class BinTree::Iterator.
// Regular low->high (++) and high->low (--) iterator
//--------------------------------------------------------
class Iterator
{
public:
//------------------------------
// Public Construction
//------------------------------
// Default Constructor
Iterator():mRoot(0),mCur(0){}
// Constructor(Node*)
Iterator(Node* root):mRoot(root){ Reset();}
// Copy constructor
Iterator(const Iterator& src):mRoot(src.mRoot),mCur(src.mCur){}
//------------------------------
// Public Commands
//------------------------------
// Reset the iterator
// atLowest : true - Reset at lowest key value (and then ++ your way through)
// false - Reset at highest key value (and then -- your way through)
void Reset(bool atLowest=true)
{
if (atLowest)
mCur = Min(mRoot);
else
mCur = Max(mRoot);
}
//------------------------------
// Public Queries
//------------------------------
// Has the iterator reached the end?
bool atEnd() const { return mCur==0; }
Node* GetNode() { return mCur; }
//------------------------------
// Public Operators
//------------------------------
// Assignment operator
Iterator& operator=(const Iterator& src)
{
mRoot = src.mRoot;
mCur = src.mCur;
return (*this);
}
// Increment operator
void operator++(int) { Inc(); }
// Decrement operator
void operator--(int)
{
Dec();
}
// Access operators
Node* operator -> () { return GetNode(); }
Node& operator* ()
{
if (atEnd())
{
throw "Iterator at end";
}
return *mCur;
}
private:
//------------------------------
// Private Helper Methods
//------------------------------
// Min: Returns node with lowest key from n and down.
// Ie the node all down to the left
Node* Min(Node* n)
{
while(n && n->GetLeftChild())
n = n->GetLeftChild();
return n;
}
// Min: Returns node with highest key from n and down.
// Ie the node all down to the right
Node* Max(Node* n)
{
while(n && n->GetRightChild())
n = n->GetRightChild();
return n;
}
//------------------------------
// Private Commands
//------------------------------
// ++
void Inc()
{
// Already at end?
if (mCur==0)
return;
if (mCur->GetRightChild())
{
// If current node has a right child, the next higher node is the
// node with lowest key beneath the right child.
mCur = Min(mCur->GetRightChild());
}
else if (mCur->IsLeftChild())
{
// No right child? Well if current node is a left child then
// the next higher node is the parent
mCur = mCur->GetParent();
}
else
{
// Current node neither is left child nor has a right child.
// Ie it is either right child or root
// The next higher node is the parent of the first non-right
// child (ie either a left child or the root) up in the
// hierarchy. Root's parent is 0.
while(mCur->IsRightChild())
mCur = mCur->GetParent();
mCur = mCur->GetParent();
}
}
// --
void Dec()
{
// Already at end?
if (mCur==0)
return;
if (mCur->GetLeftChild())
{
// If current node has a left child, the next lower node is the
// node with highest key beneath the left child.
mCur = Max(mCur->GetLeftChild());
}
else if (mCur->IsRightChild())
{
// No left child? Well if current node is a right child then
// the next lower node is the parent
mCur = mCur->GetParent();
}
else
{
// Current node neither is right child nor has a left child.
// Ie it is either left child or root
// The next higher node is the parent of the first non-left
// child (ie either a right child or the root) up in the
// hierarchy. Root's parent is 0.
while(mCur->IsLeftChild())
mCur = mCur->GetParent();
mCur = mCur->GetParent();
}
}
//------------------------------
// Private Members
//------------------------------
Node* mRoot;
Node* mCur;
}; // Iterator
//--------------------------------------------------------
// class BinTree::ParentFirstIterator.
// Traverses the tree from top to bottom. Typical usage is
// when storing the tree structure, because when reading it
// later (and inserting elements) the tree structure will
// be the same.
//--------------------------------------------------------
class ParentFirstIterator
{
public:
//------------------------------
// Public Construction
//------------------------------
// Default constructor
ParentFirstIterator():mRoot(0),mCur(0){}
// Constructor(Node*)
explicit ParentFirstIterator(Node* root):mRoot(root),mCur(0){ Reset(); }
//------------------------------
// Public Commands
//------------------------------
void Reset() { mCur = mRoot; };
//------------------------------
// Public Queries
//------------------------------
// Has the iterator reached the end?
bool atEnd() const { return mCur==0; }
Node* GetNode() { return mCur; }
//------------------------------
// Public Operators
//------------------------------
// Assignment operator
ParentFirstIterator& operator=(const ParentFirstIterator& src)
{
mRoot = src.mRoot; mCur = src.mCur; return (*this);
}
// Increment operator
void operator++(int) { Inc(); }
// Access operators
Node* operator -> () { return GetNode(); }
Node& operator* ()
{
if (atEnd())
throw "ParentFirstIterator at end";
return *GetNode();
}
private:
//------------------------------
// Private Commands
//------------------------------
void Inc()
{
// Already at end?
if (mCur==0)
return;
// First we try down to the left
if (mCur->GetLeftChild())
{
mCur = mCur->GetLeftChild();
}
else if (mCur->GetRightChild())
{
// No left child? The we go down to the right.
mCur = mCur->GetRightChild();
}
else
{
// No children? Move up in the hierarcy until
// we either reach 0 (and are finished) or
// find a right uncle.
while (mCur!=0)
{
// But if parent is left child and has a right "uncle" the parent
// has already been processed but the uncle hasn't. Move to
// the uncle.
if (mCur->IsLeftChild() && mCur->GetParent()->GetRightChild())
{
mCur = mCur->GetParent()->GetRightChild();
return;
}
mCur = mCur->GetParent();
}
}
}
//------------------------------
// Private Members
//------------------------------
Node* mRoot;
Node* mCur;
}; // ParentFirstIterator
//--------------------------------------------------------
// class BinTree::ParentLastIterator.
// Traverse the tree from bottom to top.
// Typical usage is when deleting all elements in the tree
// because you must delete the children before you delete
// their parent.
//--------------------------------------------------------
class ParentLastIterator
{
public:
//------------------------------
// Public Construction
//------------------------------
// Default constructor
ParentLastIterator():mRoot(0),mCur(0){}
// Constructor(Node*)
explicit ParentLastIterator(Node* root):mRoot(root),mCur(0){ Reset();}
//------------------------------
// Public Commands
//------------------------------
void Reset() { mCur = Min(mRoot); }
//------------------------------
// Public Queries
//------------------------------
// Has the iterator reached the end?
bool atEnd() const { return mCur==0; }
Node* GetNode() { return mCur; }
//------------------------------
// Public Operators
//------------------------------
// Assignment operator
ParentLastIterator& operator=(const ParentLastIterator& src) { mRoot = src.mRoot; mCur = src.mCur; return (*this);}
// Increment operator
void operator++(int) { Inc(); }
// Access operators
Node* operator -> () { return GetNode(); }
Node& operator* ()
{
if (atEnd())
throw "ParentLastIterator at end";
return *GetNode();
}
private:
//------------------------------
// Private Helper Methods
//------------------------------
// Min: Returns the node as far down to the left as possible.
Node* Min(Node* n)
{
while(n!=0 && (n->GetLeftChild()!=0 || n->GetRightChild()!=0))
{
if (n->GetLeftChild())
n = n->GetLeftChild();
else
n = n->GetRightChild();
}
return n;
}
//------------------------------
// Private Commands
//------------------------------
void Inc()
{
// Already at end?
if (mCur==0)
return;
// Note: Starting point is the node as far down to the left as possible.
// If current node has an uncle to the right, go to the
// node as far down to the left from the uncle as possible
// else just go up a level to the parent.
if (mCur->IsLeftChild() && mCur->GetParent()->GetRightChild())
{
mCur = Min(mCur->GetParent()->GetRightChild());
}
else
mCur = mCur->GetParent();
}
//------------------------------
// Private Members
//------------------------------
Node* mRoot;
Node* mCur;
}; // ParentLastIterator
// ByLevelIterator. Traverse tree top to bottom, level by level left to right.
// Typical usage : I don't know. Perhaps if the tree should be displayed
// in some fancy way.
// It is the most memory consuming of all iterators as it will allocate an
// array of (Size()+1)/2 Node*s.
// Impl. desc:
// mArray[0] is the current node we're looking at, initially set to mRoot.
// When ++:ing the children of mArray[0] (if any) are put last in the
// array and the array is shifted down 1 step
class ByLevelIterator
{
public:
//------------------------------
// Public Construction
//------------------------------
// Default constructor
ByLevelIterator():mRoot(0),mArray(0),mSize(0){}
// Constructor(treeRoot, elementsInTree)
ByLevelIterator(Node* root, unsigned int size):mRoot(root),mSize(size),mArray(0){ Reset();}
// Copy constructor
ByLevelIterator(const ByLevelIterator& src):mRoot(src.mRoot),mSize(src.mSize),mEndPos(src.mEndPos)
{
if (src.mArray!=0)
{
mArray = new Node*[(mSize+1)/2];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?