二叉树系列之一:二叉树

来源:互联网 发布:ubuntu ati显卡驱动 编辑:程序博客网 时间:2024/05/19 20:58

 二叉树系列包括二叉树基类、二叉搜索树、红黑树以及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_;
}
;

这里增加了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

 

 

原创粉丝点击