二叉树系列包括二叉树基类、二叉搜索树、红黑树以及AVL树。这里先讨论二叉树基类。
先看BTNode类的定义
template
<
class
T
>
struct BTNode
... {
BTNode(T d, COLOR c = RED, BF f = NORMAL, BTNode* l = nil_, BTNode* r = nil_, BTNode* p = nil_)
: data_(d), color_(c), factor_(f), lchild_(l), rchild_(r), parent_(p) ...{}
BTNode *lchild_, *rchild_, *parent_;
int color_, factor_;
T data_;
static BTNode* nil() ...{ return nil_; }
// use singleton pattern
static BTNode* createNil()
...{
if (nil_ == BTNode<T>::nil())
...{
nil_ = new BTNode();
nilify(nil_);
}
return nil_;
}
// nilify the node
static void nilify(BTNode* x = nil_)
...{
x->lchild_ = nil_;
x->rchild_ = nil_;
x->parent_ = nil_;
x->color_ = BLACK;
x->factor_ = NORMAL;
}
static void increment() ...{ refcnt_++; }
static void decrement() ...{ if (--refcnt_ == 0) delete nil_; }
private:
BTNode() : data_(T(0)), color_(RED), factor_(NORMAL), lchild_(0), rchild_(0), parent_(0) ...{}
static BTNode* nil_;
static int refcnt_;
} ;
struct BTNode
... {
BTNode(T d, COLOR c = RED, BF f = NORMAL, BTNode* l = nil_, BTNode* r = nil_, BTNode* p = nil_)
: data_(d), color_(c), factor_(f), lchild_(l), rchild_(r), parent_(p) ...{}
BTNode *lchild_, *rchild_, *parent_;
int color_, factor_;
T data_;
static BTNode* nil() ...{ return nil_; }
// use singleton pattern
static BTNode* createNil()
...{
if (nil_ == BTNode<T>::nil())
...{
nil_ = new BTNode();
nilify(nil_);
}
return nil_;
}
// nilify the node
static void nilify(BTNode* x = nil_)
...{
x->lchild_ = nil_;
x->rchild_ = nil_;
x->parent_ = nil_;
x->color_ = BLACK;
x->factor_ = NORMAL;
}
static void increment() ...{ refcnt_++; }
static void decrement() ...{ if (--refcnt_ == 0) delete nil_; }
private:
BTNode() : data_(T(0)), color_(RED), factor_(NORMAL), lchild_(0), rchild_(0), parent_(0) ...{}
static BTNode* nil_;
static int refcnt_;
} ;
这里增加了Nil节点的操作。Nil节点的增加是为了在派生类红黑树中的实现。这些操作包括了该节点的创建,该节点的引用访问以及该节点的删除。引用计数的增加使所有红黑树的叶子节点和根节点都指向了同一个Nil节点,便于红黑树的实现。
在BTree类中,主要包括了有关二叉树的一些基本操作,如二叉树的构造,二叉树的销毁以及二叉树的打印。这里值得一提的是二叉树的打印,它是按照二叉树的树形结构来打印的,看起来比较直观。对于红黑树和AVL树的调试,树形打印提供了很大的方便。
完整的代码为(BTree.h):
#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_
#include < queue >
#include < iomanip >
#include < iostream >
using std::setw;
using std::cout;
using std::queue;
using std::ostream;
enum COLOR ... { RED = 0, BLACK } ;
enum BF ... { LOW = -2, LESS, NORMAL, MORE, HIGH } ;
template < class T >
struct BTNode
... {
BTNode(T d, COLOR c = RED, BF f = NORMAL, BTNode* l = nil_, BTNode* r = nil_, BTNode* p = nil_)
: data_(d), color_(c), factor_(f), lchild_(l), rchild_(r), parent_(p) ...{}
BTNode *lchild_, *rchild_, *parent_;
int color_, factor_;
T data_;
static BTNode* nil() ...{ return nil_; }
// use singleton pattern
static BTNode* createNil()
...{
if (nil_ == BTNode<T>::nil())
...{
nil_ = new BTNode();
nilify(nil_);
}
return nil_;
}
// nilify the node
static void nilify(BTNode* x = nil_)
...{
x->lchild_ = nil_;
x->rchild_ = nil_;
x->parent_ = nil_;
x->color_ = BLACK;
x->factor_ = NORMAL;
}
static void increment() ...{ refcnt_++; }
static void decrement() ...{ if (--refcnt_ == 0) delete nil_; }
private:
BTNode() : data_(T(0)), color_(RED), factor_(NORMAL), lchild_(0), rchild_(0), parent_(0) ...{}
static BTNode* nil_;
static int refcnt_;
} ;
template < class T > BTNode < T >* BTNode < T > ::nil_ = BTNode < T > ::nil();
template < class T > int BTNode < T > ::refcnt_ = 0 ;
template < class T >
class BTree
... {
public:
BTree(T data = T())
...{
BTNode<T>::createNil();
BTNode<T>::increment();
root_ = new BTNode<T>(data);
BTNode<T>::nilify(root_);
}
virtual ~BTree() ...{ destroy(root_); BTNode<T>::decrement(); }
int height() const ...{ return height(root_); }
void print(ostream& out) ...{ print(out, root_); }
protected:
BTNode<T>* root_;
private:
int height(BTNode<T>* x) const
...{
if (x == BTNode<T>::nil()) return 0;
int hl = height(x->lchild_);
int hr = height(x->rchild_);
if (hl > hr) return ++hl;
else return ++hr;
}
void destroy(BTNode<T>* x)
...{
if (x != BTNode<T>::nil())
...{
destroy(x->lchild_);
destroy(x->rchild_);
delete x;
}
}
void print(ostream& out, BTNode<T>* p)
...{
queue<BTNode<T>* > node;
int level = 0, h = height(p) - 1;
for ( int i = 1; i < 2<<h; i++)
...{
// specify the print format
if (i == 1<<level) out << endl << setw(2 << (h - level++));
else out << setw(4 << (h - level + 1));
// print the data, '-' for nil node
if (p != BTNode<T>::nil()) out << p->data_;
else out << '-';
// push the left and right child
node.push(p->lchild_); node.push(p->rchild_);
// pop the node to print
p = node.front(); node.pop();
}
}
} ;
template < class T >
ostream & operator << (ostream & out , BTree < T >& bt)
... {
bt.print(out);
return out;
}
#endif
#define _BINARY_TREE_H_
#include < queue >
#include < iomanip >
#include < iostream >
using std::setw;
using std::cout;
using std::queue;
using std::ostream;
enum COLOR ... { RED = 0, BLACK } ;
enum BF ... { LOW = -2, LESS, NORMAL, MORE, HIGH } ;
template < class T >
struct BTNode
... {
BTNode(T d, COLOR c = RED, BF f = NORMAL, BTNode* l = nil_, BTNode* r = nil_, BTNode* p = nil_)
: data_(d), color_(c), factor_(f), lchild_(l), rchild_(r), parent_(p) ...{}
BTNode *lchild_, *rchild_, *parent_;
int color_, factor_;
T data_;
static BTNode* nil() ...{ return nil_; }
// use singleton pattern
static BTNode* createNil()
...{
if (nil_ == BTNode<T>::nil())
...{
nil_ = new BTNode();
nilify(nil_);
}
return nil_;
}
// nilify the node
static void nilify(BTNode* x = nil_)
...{
x->lchild_ = nil_;
x->rchild_ = nil_;
x->parent_ = nil_;
x->color_ = BLACK;
x->factor_ = NORMAL;
}
static void increment() ...{ refcnt_++; }
static void decrement() ...{ if (--refcnt_ == 0) delete nil_; }
private:
BTNode() : data_(T(0)), color_(RED), factor_(NORMAL), lchild_(0), rchild_(0), parent_(0) ...{}
static BTNode* nil_;
static int refcnt_;
} ;
template < class T > BTNode < T >* BTNode < T > ::nil_ = BTNode < T > ::nil();
template < class T > int BTNode < T > ::refcnt_ = 0 ;
template < class T >
class BTree
... {
public:
BTree(T data = T())
...{
BTNode<T>::createNil();
BTNode<T>::increment();
root_ = new BTNode<T>(data);
BTNode<T>::nilify(root_);
}
virtual ~BTree() ...{ destroy(root_); BTNode<T>::decrement(); }
int height() const ...{ return height(root_); }
void print(ostream& out) ...{ print(out, root_); }
protected:
BTNode<T>* root_;
private:
int height(BTNode<T>* x) const
...{
if (x == BTNode<T>::nil()) return 0;
int hl = height(x->lchild_);
int hr = height(x->rchild_);
if (hl > hr) return ++hl;
else return ++hr;
}
void destroy(BTNode<T>* x)
...{
if (x != BTNode<T>::nil())
...{
destroy(x->lchild_);
destroy(x->rchild_);
delete x;
}
}
void print(ostream& out, BTNode<T>* p)
...{
queue<BTNode<T>* > node;
int level = 0, h = height(p) - 1;
for ( int i = 1; i < 2<<h; i++)
...{
// specify the print format
if (i == 1<<level) out << endl << setw(2 << (h - level++));
else out << setw(4 << (h - level + 1));
// print the data, '-' for nil node
if (p != BTNode<T>::nil()) out << p->data_;
else out << '-';
// push the left and right child
node.push(p->lchild_); node.push(p->rchild_);
// pop the node to print
p = node.front(); node.pop();
}
}
} ;
template < class T >
ostream & operator << (ostream & out , BTree < T >& bt)
... {
bt.print(out);
return out;
}
#endif