二叉树

来源:互联网 发布:精虫上脑怎么办知乎 编辑:程序博客网 时间:2024/06/05 05:56

 

二叉树的实现[r1] 1
// FileName;BTNode.h
//
二叉树类声明头文件 
#ifndef BTNODE
#define BTNODE// 
表示二叉树的节点
template <typename T>
class BTNode
{
   public:
                // BTNode 
是类的实现,使得数据成为公有成员简化了类函数的构造,
                //
结合BTNode的应用场合,并不违反面向对象设计原则 
                T data;
                BTNode<T> *left, *right;
[r2] 
// 默认构造函数。数据项未被初始化,左、右指针为空 
                BTNode():left(NULL),right(NULL)
                {}
// 标准构造函数,初始化数据成员,左、右子树指针的默认参数值都为NULL
                BTNode (const T& item, BTNode<T> *lptr = NULL
                                 BTNode<T> *rptr = NULL):
                                data(item), left(lptr), right(rptr){}
                
};
#endif        // BTNODE
 
 
// FileName: BTreelib.h
// 
二叉树类库函数头文件
#ifndef TREE_LIBRARY_FUNCTIONS
#define TREE_LIBRARY_FUNCTIONS
#include <iostream>
#include <strstream>
[r3] #include <iomanip>
#include <string>
#include <queue>
#ifndef NULL
#include <cstddef>
[r4] #endif  // NULL
#include "BTNode.h"                // use BTNode class
using namespace std;
 
// 中序递归访问二叉树,visit函数是定制函数
template <typename T>
void inOrder(BTNode<T> *t, void visit(T& item));
// 后序递归访问二叉树,visit函数是定制函数 
template <typename T>
void postOrder(BTNode<T> *t, void visit(T& item));
 
//有先序遍历
template <typename T>
void preOrder(BTNode<T> *t, void visit(T& item));
 
// 按照层次顺序遍历访问二叉树,visit是定制函数 
template <typename T>
void levelOrder(BTNode<T> *t, void visit(T& item));
 
// 在引用参数count中累计二叉树叶节点的的数目,count被初始化为
template <typename T>
void countLeaf(BTNode<T> *t, int& count);
 
// 返回二叉树的深度 
template <typename T>
int depth (BTNode<T> *t);
 
// 生成树t的副本,返回新的副本的指针
template <typename T>
BTNode<T> *copyTree(BTNode<T> *t);
 
// 遍历并删除二叉树的节点
template <typename T>
void deleteTree(BTNode<T> *t);
 
// deleteTree()删除树的所有节点,并将树根节点赋值为空
template <typename T>
void clearTree(BTNode<T> * & t);
 
// 垂直显示二叉树,输出节点值
//
节点值的宽度不大于dataWidth,屏幕宽度为screenWidth 
template <typename T>
void displayTree(const BTNode<T> *t, const int dataWidth=1,const int screenWidth=64);
 
//各个函数的实现
 
template <typename T>
void inOrder(BTNode<T> *t, void visit(T& item))
{
   // 
当子树为空时,递归遍历终止
   if (t != NULL)
   {
          inOrder(t->left, visit);        // 
遍历左子树
          visit(t->data);        // 
访问节点 
          inOrder(t->right, visit);        // 
遍历右子树
   }
}
 
template <typename T>
void postOrder(BTNode<T> *t, void visit(T& item))
{
   // 
当子树为空时,递归遍历终止
   if (t != NULL)
   {
          postOrder(t->left, visit);        // 
遍历左子树
          postOrder(t->right, visit);        // 
遍历右子树
          visit(t->data);                        // 
访问节点 
   }
}
 
template <typename T>
void preOrder(BTNode<T> *t, void visit(T& item))
{
      // 当子树为空时,递归遍历终止
   if (t != NULL)
   {
visit(t->data);                   // 访问节点 
    preOrder(t->left, visit);        // 
遍历左子树
    preOrder(t->right, visit);        // 
遍历右子树
         
   }
}
 
template <typename T>
void levelOrder(BTNode<T> *t, void visit(T& item))
[r5] {
   // 
存储每个节点的兄弟节点到队列中,这样可以按树的下一层的顺序访问它们
   queue<BTNode<T> *> q;
   BTNode<T> *p;
   // 在队列中插入根节点来初始化队列
   q.push(t);
   // 继续迭代过程,直到队列空 
   while(!q.empty())
   {
          // 
从队列中删除前端节点,并访问节点
          p = q.front();
          q.pop();
          visit( p->data);
  // 如果存在左子节点,将它插入到队列
          if(p->left != NULL)
                        q.push(p->left);
          // 
如果存在右子节点,插入到队列,使它紧邻其兄弟
          if(p->right != NULL)
                        q.push(p->right);
   }
}
 
//引用参数count被初始化为,计算叶子节点的个数
template <typename T>
void countLeaf (BTNode<T> *t, int& count)
{
   if (t != NULL)
   {
          // 
检查t是否为叶节点
          // 
如果是,count1
          if (t->left == NULL && t->right == NULL)//
此时说明是叶子节点
                 count++;
          countLeaf(t->left, count);        // 
左子树遍历,计数 
          countLeaf(t->right, count);        // 
右子树遍历,计数
   }
}
 
//使用后序遍历算法决定树深度
[r6] template <typename T>
int depth (BTNode<T> *t)
{
   int depthLeft, depthRight, depthval;//
分别用来记录左子树,右子树和总树的//深度
   if (t == NULL)
          // 
空树的深度定为-1
          depthval = -1;
   else
        {
                //
查找t的左子树的深度
                depthLeft= depth(t->left);
                //
查找t的右子树的深度
                depthRight= depth(t->right);
                //
t为根的树的深度为:1+ (两棵子树的最大深度) 
                depthval = 1 +
                        (depthLeft >= depthRight ? depthLeft : depthRight);
   }
   return depthval;
}
 
template <typename T>
BTNode<T> *copyTree(BTNode<T> *t)
[r7] {
   // newNode 
指向算法产生的新节点,
   //newLptr
newRptr指向newNode的左、右子树
   BTNode<T> *newLeft, *newRight, *newNode;
   // 到达空树时停止递归遍历
   if (t == NULL)
          return NULL;
   // 自底向上构造新树:先构造两个子树,然后构造父节点。
   // 
在节点t,生成左子树的副本,将其根节点指针赋值给newLeft
   newLeft = copyTree(t->left);
   // 
生成右子树的副本,将其根节点指针赋值给newRight 
   newRight = copyTree(t->right);
   // 生成新节点,其节点值与t的值相同,其子节点是被复制的t的子树
   newNode = new BTNode<T> (t->data, newLeft, newRight);
   // 返回新复制的树的根节点的指针
   return newNode;
}
 
template <typename T>
void deleteTree(BTNode<T> *t)
[r8] 
{
        // 
后序遍历,删除t的左、右子树,然后删除节点t
        if (t != NULL)
        {
                deleteTree(t->left);
                deleteTree(t->right);
                delete t;
        }
}
 
template <typename T>
void clearTree(BTNode<T> * & t)
{
        deleteTree(t);
        t = NULL//
此时根为NULL 
}
 
//辅助结构
//
存放displayTree中节点坐标(xy)的记录
struct Info
{
        //
默认构造函数 
        Info() {} 
        //
初始化构造函数
        Info(int indent, int level):xIndent(indent),yLevel(level) {}; 
        int xIndent,yLevel;
};
[r9] 
template <typename T>
void displayTree(BTNode<T> *t, const int dataWidth,const int screenWidth=64)
[r10] {
   // 
存储每个节点的队列
   queue<BTNode<T> *> q;
   //
存放节点打印信息的队列; 
   
   queue<Info>QI; 
   BTNode<T> *currNode;
   Info currInfo; 
   int units (screenWidth/dataWidth); 
   int offset = units/2;
   //
当前节点的列坐标  
   int currlevel = -1;
   //
当前节点的同层的前一节点的行坐标 
   int preX;    
        
   //
如果树为空,退出 
   if (t == NULL)
          return;
   // 在队列q中插入根节点来初始化队列
   q.push(t);
   //
在队列QI中插入根节点坐标初始化队列 
   QI.push(Info(offset,0));
   // 继续迭代过程,直到队列空 
   while(!q.empty())
   {
          // 
从队列中删除前端节点,并访问节点
          currNode = q.front();
          q.pop();
          currInfo = QI.front();
          QI.pop(); 
          if( currInfo.yLevel != currlevel )
          {
                   //
换两行         
                   cout<<"/n/n" ;     
                  //
新行,起始位置为0
                  preX = 0;
                  //
子女节点的偏移量为 上层节点的1/2  
                  offset /= 2;   
                  //
更新当前节点坐标层次 
                  currlevel = currInfo.yLevel;       
          }
          
          //
在相应位置输出节点队列头部元素的值,类型为T
          //
我们假定类型T定义了合适的<<操作符 
          cout<<setw((currInfo.xIndent-preX)*dataWidth)
                  <<currNode->data;  
          
          if( currNode->left != NULL )
          {
                  //
左子节点入队
                  q.push(currNode->left) ;
                  //
左子节点位置信息入队
                  QI.push(Info(currInfo.xIndent-offset,currInfo.yLevel+1));
          }
          if( currNode->right != NULL )
          {
                  //
右子节点入队
                  q.push(currNode->right) ;
                  //
右子节点位置信息入队
                  QI.push(Info(currInfo.xIndent+offset,currInfo.yLevel+1));
          }      
          preX = currInfo.xIndent;
   } //while
循环
}
        
#endif   // TREE_LIBRARY_FUNCTIONS
 
 
// File: testBTree.cpp
 
// 此程序演示二叉树的各种算法
// 首先构建一棵二叉树,在屏幕上垂直输出
// 中序、后序及层次遍历二叉树 
// 计算树的高度,并计算叶节点个数
// 并验证了复制、删除二叉树的操作 
 
#include <iostream>
 
#include "BTNode.h"                // BTNode 
#include "BTreelib.h"        // BTNode 
 
using namespace std;
 
//实用函数makeCharTree,生成一棵以字符为节点数据的二叉树
BTNode<char> *makeCharTree();
 
//遍历算法的visit函数,输出节点数据值 
void printChar(char& elem)
{
string seperator = "  "
cout <<  elem << seperator;
 
int main()
{
//二叉树的根 
BTNode<char> *root1, *root2;
 
// 构造二叉树 
root1 = makeCharTree();
 
// 显示树
cout << "原始树的图示:" << endl;
const int charWidth=1;
const int ScreenWidth=64;
displayTree(root1, charWidth,ScreenWidth);
cout << endl << endl;
 
//节点的中序遍历
cout << "中序遍历:" ;
inOrder(root1, printChar);
cout << endl;
 
//节点的后序遍历
cout << "后序遍历:" ;
postOrder(root1, printChar);
cout << endl;
 
//节点的层次遍历
cout << "层次遍历:" ;
levelOrder(root1, printChar);
cout << endl<<endl;
 
//叶结点计数
int leafCount = 0;
countLeaf(root1, leafCount);
cout << "叶节点数目是:"
 << leafCount << endl
cout << "树的深度是:"
 << depth (root1) <<endl
 
//生成root1的副本,根为root2
root2 = copyTree(root1);
 
// 显示树的副本 
cout << "原始树的副本的图示:" << endl;
displayTree(root2, charWidth,ScreenWidth);
cout << endl;
 
// 清空两棵树
clearTree(root1);
clearTree(root2);
 
cout << "root1调用的clearTree之后的图示:" << endl;
displayTree(root1, charWidth,ScreenWidth);
cout << endl << endl;
 
cout<<"按回车键结束程序:" << endl;
cin.get(); 
return 0;
}
 
 
BTNode<char> *makeCharTree()
{
// 9 BTNode 指针,指向9个节点项
BTNode<char> *root, *b, *c, *d, *e, *f, *g, *h, *i;
g = new BTNode<char> ('G');
h = new BTNode<char> ('H');
i = new BTNode<char> ('I');
d = new BTNode<char> ('D',(BTNode<char> *)NULL, g);
e = new BTNode<char> ('E',h, i);
f = new BTNode<char> ('F');
b = new BTNode<char> ('B',d, (BTNode<char> *)NULL);
c = new BTNode<char> ('C',e, f);
root = new BTNode<char> ('A',b, c);
return root;
}
 
 二叉树的实现(2[r11] 
// BinTreeNode.h
//声明二叉树类
template<typename Type> class BinaryTree;
 
template<typename Type> class BinTreeNode{
 
 public:
    friend class BinaryTree<Type>;[r12] 
    BinTreeNode():m_pleft(NULL),m_pright(NULL){}
    BinTreeNode(Type item,BinTreeNode<Type> *left=NULL,BinTreeNode<Type> *right=NULL)
       :m_data(item),m_pleft(left),m_pright(right){}
 
    Type GetData() const;       //get thd data
    BinTreeNode<Type> *GetLeft() const;       //get the left node
    BinTreeNode<Type> *GetRight() const;   //get the right node
 
    void SetData(const Type data);         //change the data
    void SetLeft(const BinTreeNode<Type> *left); //change thd left node
    void SetRight(const BinTreeNode<Type> *right);   //change the right node
 
    void InOrder();      //inorder the tree with the root of the node
    void PreOrder(); //perorder the tree with the root of the node
    void PostOrder(); //postoder the tree with the root of the node
   
    int Size();          //get size
    int Height();     //get height
    BinTreeNode<Type> *Copy(const BinTreeNode<Type> *copy); //copy the node
    void Destroy(){      //destroy the tree with the root of the node
       if(this!=NULL){
           this->m_pleft->Destroy();
           this->m_pright->Destroy();
           delete this;
       }
    }
 
    friend bool equal(const BinTreeNode<Type> *s,const BinTreeNode<Type> *t); //is equal?
 
private:
    BinTreeNode<Type> *m_pleft,*m_pright;
    Type m_data;
};
 
template<typename Type> Type BinTreeNode<Type>::GetData() const{
    return this!=NULL?m_data:-1;
}
 
template<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::GetLeft() const{
    return this!=NULL?m_pleft:NULL;
}
 
template<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::GetRight() const{
    return this!=NULL?m_pright:NULL;
}
 
template<typename Type> void BinTreeNode<Type>::SetData(const Type data){
    if(this!=NULL){
       m_data=data;
    }
}
 
template<typename Type> void BinTreeNode<Type>::SetLeft(const BinTreeNode<Type> *left){
    if(this!=NULL){
       m_pleft=left;
    }
}
 
template<typename Type> void BinTreeNode<Type>::SetRight(const BinTreeNode<Type> *right){
    if(this!=NULL){
       m_pright=right;
    }
}
 
template<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::Copy(const BinTreeNode<Type> *copy){
    if(copy==NULL){
       return NULL;
    }
 
    BinTreeNode<Type> *temp=new BinTreeNode<Type>(copy->m_data);
    temp->m_pleft=Copy(copy->m_pleft);
    temp->m_pright=Copy(copy->m_pright);
    return temp;
}
 
template<typename Type> bool equal(const BinTreeNode<Type> *s,const BinTreeNode<Type> *t){
    if(s==NULL&&t==NULL){
       return 1;
    }
if(s&&t&&s->m_data==t->m_data&&equal(s->m_pleft,t->m_pleft)&&equal(s->m_pright,t->m_pright)){
       return 1;
    }
    return 0;
}
 
template<typename Type> void BinTreeNode<Type>::InOrder(){
    if(this!=NULL){
       this->m_pleft->InOrder();
       cout<<"--->"<<this->m_data;
       this->m_pright->InOrder();
    }
}
 
template<typename Type> void BinTreeNode<Type>::PreOrder(){
    if(this!=NULL){
       cout<<"--->"<<this->m_data;
       this->m_pleft->PreOrder();
       this->m_pright->PreOrder();
    }
}
 
template<typename Type> void BinTreeNode<Type>::PostOrder(){
    if(this!=NULL){
       this->m_pleft->PostOrder();
       this->m_pright->PostOrder();
       cout<<"--->"<<this->m_data;
    }
}
 
template<typename Type> int BinTreeNode<Type>::Size(){
    if(this==NULL){
       return 0;
    }
    return 1+this->m_pleft->Size()+this->m_pright->Size();
}
 
template<typename Type> int BinTreeNode<Type>::Height(){
    if(this==NULL){
       return -1;
    }
    int lheight,rheight;
    lheight=this->m_pleft->Height();
    rheight=this->m_pright->Height();
    return 1+(lheight>rheight?lheight:rheight);
}
 
BinaryTree.h
 
#include "BinTreeNode.h"
 
template<typename Type> class BinaryTree{
public:
    BinaryTree():m_proot(NULL){}
    BinaryTree(const Type stop):m_stop(stop),m_proot(NULL){}
    BinaryTree(BinaryTree<Type>& copy);
    virtual ~BinaryTree(){
       m_proot->Destroy();
    }
    virtual bool IsEmpty(){     //is empty?
       return m_proot==NULL;
    }
   
    virtual BinTreeNode<Type> *GetLeft(BinTreeNode<Type> *current);    //get the left node
    virtual BinTreeNode<Type> *GetRight(BinTreeNode<Type> *current);//get the right node
    virtual BinTreeNode<Type> *GetParent(BinTreeNode<Type> *current);//ghe thd parent
    const BinTreeNode<Type> *GetRoot() const; //get root
   
    virtual bool Insert(const Type item);     //insert a new node
    virtual BinTreeNode<Type> *Find(const Type item) const; //find thd node with the data
 
    void InOrder();  
    void PreOrder();
    void PostOrder();
 
    int Size();       //get size
    int Height(); //get height
 
    BinaryTree<Type>& operator=(const BinaryTree<Type> copy);   //evaluate node
 
    friend bool operator== <Type>(const BinaryTree<Type> s,const BinaryTree<Type> t);//is equal?
    friend ostream& operator<< <Type>(ostream& ,BinaryTree<Type>&);    //output the data
    friend istream& operator>> <Type>(istream& ,BinaryTree<Type>&);    //input the data
      
private:
    Type m_stop;      //just using for input the data;
    BinTreeNode<Type> *m_proot;
 
    //find the parent of current in the tree with the root of start
    BinTreeNode<Type> *GetParent(BinTreeNode<Type> *start,BinTreeNode<Type> *current);
    void Print(BinTreeNode<Type> *start,int n=0); //print the tree with the root of start
};
 
template<typename Type> BinaryTree<Type>::BinaryTree(BinaryTree<Type>& copy){
    if(copy.m_proot){
       this->m_stop=copy.m_stop;
    }
    m_proot=m_proot->Copy(copy.m_proot);
}
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetLeft(BinTreeNode<Type> *current){
    return m_proot&&current?current->m_pleft:NULL;
}
 
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetRight(BinTreeNode<Type> *current){
    return m_proot&&current?current->m_pright:NULL;
}
 
template<typename Type> const BinTreeNode<Type>* BinaryTree<Type>::GetRoot() const{
    return m_proot;
}
 
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetParent(BinTreeNode<Type> *start, BinTreeNode<Type> *current){
    if(start==NULL||current==NULL){
       return NULL;
    }
    if(start->m_pleft==current||start->m_pright==current){
       return start;
    }
    BinTreeNode<Type> *pmove;
    if((pmove=GetParent(start->m_pleft,current))!=NULL){//find the parent in the left subtree
       return pmove;
    }
    else{
       return GetParent(start->m_pright,current);    //find the parent in the right subtree
    }
}
 
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetParent(BinTreeNode<Type> *current){
    return m_proot==NULL||current==m_proot?NULL:GetParent(m_proot,current);  
}
 
 
template<typename Type> bool BinaryTree<Type>::Insert(const Type item){
    BinTreeNode<Type> *pstart=m_proot,*newnode=new BinTreeNode<Type>(item);
    if(m_proot==NULL){
       m_proot=newnode;
       return 1;
    }
    while(1){
       if(item==pstart->m_data){
           cout<<"The item "<<item<<" is exist!"<<endl;
           return 0;
       }
       if(item<pstart->m_data){
           if(pstart->m_pleft==NULL){
              pstart->m_pleft=newnode;
              return 1;
           }
           pstart=pstart->m_pleft; //if less than the node then insert to the left subtree
       }
       else{
           if(pstart->m_pright==NULL){
              pstart->m_pright=newnode;
              return 1;
           }
           pstart=pstart->m_pright;//if more than the node then insert to the right subtree
       }
    }
}
 
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::Find(const Type item) const{
    BinTreeNode<Type> *pstart=m_proot;
    while(pstart){
       if(item==pstart->m_data){
           return pstart;
       }
       if(item<pstart->m_data){
           pstart=pstart->m_pleft; //if less than the node then find in the left subtree
       }
       else{
           pstart=pstart->m_pright;//if more than the node then find in the right subtree
       }
    }
    return NULL;
}
 
template<typename Type> void BinaryTree<Type>::Print(BinTreeNode<Type> *start, int n){
    if(start==NULL){
       for(int i=0;i<n;i++){
           cout<<"     ";
       }
       cout<<"NULL"<<endl;
       return;
    }
    Print(start->m_pright,n+1); //print the right subtree
    for(int i=0;i<n;i++){    //print blanks with the height of the node
       cout<<"     ";
    }
    if(n>=0){
       cout<<start->m_data<<"--->"<<endl;//print the node
    }
    Print(start->m_pleft,n+1); //print the left subtree
}
 
template<typename Type> BinaryTree<Type>& BinaryTree<Type>::operator=(const BinaryTree<Type> copy){
    if(copy.m_proot){
       this->m_stop=copy.m_stop;
    }
    m_proot=m_proot->Copy(copy.m_proot);
    return *this;
}
 
template<typename Type> ostream& operator<<(ostream& os,BinaryTree<Type>& out){
    out.Print(out.m_proot);
    return os;
}
 
template<typename Type> istream& operator>>(istream& is,BinaryTree<Type>& in){
    Type item;
    cout<<"initialize the tree:"<<endl<<"Input data(end with "<<in.m_stop<<"!):";
    is>>item;
    while(item!=in.m_stop){ //m_stop is the end of input
       in.Insert(item);
       is>>item;
    }
    return is;
}
 
template<typename Type> bool operator==(const BinaryTree<Type> s,const BinaryTree<Type> t){
    return equal(s.m_proot,t.m_proot);
}
 
template<typename Type> void BinaryTree<Type>::InOrder(){
    this->m_proot->InOrder();
}
 
template<typename Type> void BinaryTree<Type>::PreOrder(){
    this->m_proot->PreOrder();
}
 
template<typename Type> void BinaryTree<Type>::PostOrder(){
    this->m_proot->PostOrder();
}
 
template<typename Type> int BinaryTree<Type>::Size(){
    return this->m_proot->Size();
 
}
 
template<typename Type> int BinaryTree<Type>::Height(){
    return this->m_proot->Height();
}
 
Test.cpp
 
#include <iostream>
 
using namespace std;
 
#include "BinaryTree.h"
 
int main(){
    BinaryTree<int> tree(-1);
// int init[10]={3,6,0,2,8,4,9,1,5,7};
    int init[30]={17,6,22,29,14,0,21,13,27,18,2,28,8
       ,26,3,12,20,4,9,23,15,1,11,5,19,24,16,7,10,25};
    for(int i=0;i<30;i++){
       tree.Insert(init[i]);
    }
    //cin>>tree;
    cout<<tree<<endl;
 
    cout<<tree.GetParent(tree.Find(20))->GetData()<<endl;
    cout<<tree.Find(15)->GetRight()->GetData()<<endl;
 
    cout<<"size="<<tree.Size()<<endl;
    cout<<"height="<<tree.Height()<<endl;
 
    tree.InOrder();
    cout<<endl<<endl;
    tree.PreOrder();
    cout<<endl<<endl;
    tree.PostOrder();
    cout<<endl<<endl;
   
 
    BinaryTree<int> tree2=tree;
    cout<<tree2<<endl;
 
    cout<<tree2.GetParent(tree2.Find(20))->GetData()<<endl;
    cout<<tree2.Find(15)->GetRight()->GetData()<<endl;
 
    cout<<(tree==tree2)<<endl;
    return 0;
}
 
 //二叉树[r13] 3
 //BTNode.h
#ifndef BTNODE
#define BTNODE// 
表示二叉树的节点
template<class TYPE>
class BTree;
 
template <typename T>
class BTNode
{
private:
        T data;
        BTNode<T> *left, *right;
public:
        // 
默认构造函数。数据项未被初始化,左、右指针为空
        BTNode():left(NULL),right(NULL)
        {}
        // 
标准构造函数,初始化数据成员,左、右子树指针的默认参数值都为NULL
        BTNode (const T& item, BTNode<T> *lptr = NULL,
               BTNode<T> *rptr = NULL):
        data(item), left(lptr), right(rptr){}
        T GetData() const;             //get thd data
        BTNode<T> *GetLeft() const;           //get the left node
        BTNode<T> *GetRight() const;   //get the right node
        void SetData(const T data1);                  //change the data
        void SetLeft(const BTNode<T> *left1); //change thd left node
        void SetRight(const BTNode<T> *right1);       //change the right node
        BTNode<T> *Copy(const BTNode<T> *copy);       //copy the node
        friend bool equal(const BTNode<T> *s, const BTNode<T> *t);//is equal?
};
 
template<typename Type>
Type BTNode<Type>::GetData() const{
        return this!=NULL?data:-1;
}
 
template<typename Type>
BTNode<Type>* BTNode<Type>::GetLeft() const{
        return this!=NULL?left:NULL;
}
 
template<typename Type>
BTNode<Type>* BTNode<Type>::GetRight() const{
        return this!=NULL?right:NULL;
}
 
template<typename Type>
void BTNode<Type>::SetData(const Type data1){
        if(this!=NULL){
               data=data1;
        }
}
 
template<typename Type>
void BTNode<Type>::SetLeft(const BTNode<Type> *left1){
        if(this!=NULL){
               left=left1;
        }
}
 
template<typename Type>
void BTNode<Type>::SetRight(const BTNode<Type> *right1){
        if(this!=NULL){
               right=right1;
        }
}
 
template<typename Type>
BTNode<Type>* BTNode<Type>::Copy(const BTNode<Type> *copy){
        if(copy==NULL){
               return NULL;
        }
 
        BTNode<Type> *temp=new BTNode<Type>(copy->data);
        temp->left=Copy(copy->left);
        temp->right=Copy(copy->right);
        return temp;
}
 
template<typename Type>
bool equal(const BTNode<Type> *s,const BTNode<Type> *t){
        if(s==NULL&&t==NULL){
               return 1;
        }
        if(s&&t&&s->data==t->data&&equal(s->left,t->left)&&equal(s->right,t->right)){
               return 1;
        }
        return 0;
}
 
#endif        // BTNODE
 
 //BTree.h
#ifndef TREE_LIBRARY_FUNCTIONS
#define TREE_LIBRARY_FUNCTIONS
#include <iomanip>
#include <string>
#include <queue>
#include <fstream>
#include "BTNode.h"
using namespace std;
 
template<class T>
class BTree
{
public:
        BTree():root(NULL),count(0){}
        virtual~BTree()
        {}
 
        // 
中序递归访问二叉树,visit函数是定制函数
        void inOrder(BTNode<T> *t, void visit(T& item));
 
        // 
后序递归访问二叉树,visit函数是定制函数
        void postOrder(BTNode<T> *t, void visit(T& item));
 
        //
有先序遍历
        void preOrder(BTNode<T> *t, void visit(T& item));
 
        // 
按照层次顺序遍历访问二叉树,visit是定制函数
        void levelOrder(BTNode<T> *t, void visit(T& item));
 
        // 
在引用参数count中累计二叉树叶节点的的数目,count被初始化为0
        int countLeaf(BTNode<T> *t, int& count);
 
        // 
返回二叉树的深度
        int depth (BTNode<T> *t);
 
        // 
生成树t的副本,返回新的副本的指针
        BTNode<T> *copyTree(BTNode<T> *t);
 
        // 
遍历并删除二叉树的节点
        void deleteTree(BTNode<T> *t);
 
        // 
deleteTree()删除树的所有节点,并将树根节点赋值为空
        void clearTree(BTNode<T> * & t);
 
        // 
垂直显示二叉树,输出节点值
        //
节点值的宽度不大于dataWidth,屏幕宽度为screenWidth
        void displayTree(const BTNode<T> *t, const int dataWidth=1,const int screenWidth=64);
 
        //
查找//find thd node with the data
        BTNode<T> *Find(const T item) const;
 
        friend bool operator== <T>(const BTree<T> s,const BTree<T> t);//is equal?
 
private:
 
        int count;//
叶子节点的个数
        BTNode<T>* root;
        //
辅助结构
        //
存放displayTree中节点坐标(xy)的记录
        struct Info
        {
               //
默认构造函数
               Info() {}
               //
初始化构造函数
               Info(int indent, int level):xIndent(indent),yLevel(level) {};
               int xIndent,yLevel;
        };
};
 
template <typename T>
void BTree<T>::inOrder(BTNode<T> *t, void visit(T& item))
{
        // 
当子树为空时,递归遍历终止
        if (t != NULL)
        {
               inOrder(t->left, visit);        // 
遍历左子树
               visit(t->data);        // 
访问节点
               inOrder(t->right, visit);        // 
遍历右子树
        }
}
 
template <typename T>
void BTree<T>::postOrder(BTNode<T> *t, void visit(T& item))
{
        // 
当子树为空时,递归遍历终止
        if (t != NULL)
        {
               postOrder(t->left, visit);        // 
遍历左子树
               postOrder(t->right, visit);        // 
遍历右子树
               visit(t->data);                        // 
访问节点
        }
}
 
template <typename T>
void BTree<T>::preOrder(BTNode<T> *t, void visit(T& item))
{
        // 
当子树为空时,递归遍历终止
        if (t != NULL)
        {
               visit(t->data);                   // 
访问节点
               preOrder(t->left, visit);        // 
遍历左子树
               preOrder(t->right, visit);        // 
遍历右子树
        }
}
 
template <typename T>
void BTree<T>::levelOrder(BTNode<T> *t, void visit(T& item))
{
        // 
存储每个节点的兄弟节点到队列中,这样可以按树的下一层的顺序访问它们
        queue<BTNode<T> *> q;
        BTNode<T> *p;
        // 
在队列中插入根节点来初始化队列
        q.push(t);
        // 
继续迭代过程,直到队列空
        while(!q.empty())
        {
               // 
从队列中删除前端节点,并访问节点
               p = q.front();
               q.pop();
               visit( p->data);
               // 
如果存在左子节点,将它插入到队列
               if(p->left != NULL)
                       q.push(p->left);
               // 
如果存在右子节点,插入到队列,使它紧邻其兄弟
               if(p->right != NULL)
                       q.push(p->right);
        }
}
 
//
引用参数count被初始化为,计算叶子节点的个数
template <typename T>
int BTree<T>::countLeaf (BTNode<T> *t, int& count)
{
        if (t != NULL)
        {
               // 
检查t是否为叶节点
               // 
如果是,count1
               if (t->left == NULL && t->right == NULL)//
此时说明是叶子节点
                       count++;
               countLeaf(t->left, count);        // 
左子树遍历,计数
               countLeaf(t->right, count);        // 
右子树遍历,计数
        }
        return count;
}
 
//
使用后序遍历算法决定树深度
template <typename T>
int BTree<T>::depth (BTNode<T> *t)
{
        int depthLeft, depthRight, depthval;//
分别用来记录左子树,右子树和总树的//深度
        if (t == NULL)
               // 
空树的深度定为-1
               depthval = -1;
        else
        {
               //
查找t的左子树的深度
               depthLeft= depth(t->left);
               //
查找t的右子树的深度
               depthRight= depth(t->right);
               //
t为根的树的深度为:1+ (两棵子树的最大深度)
               depthval = 1 +
                       (depthLeft >= depthRight ? depthLeft : depthRight);
        }
        return depthval;
}
 
template <typename T>
BTNode<T>* BTree<T>::copyTree(BTNode<T> *t)
{
        // newNode 
指向算法产生的新节点,
        //newLptr
newRptr指向newNode的左、右子树
        BTNode<T> *newLeft, *newRight, *newNode;
        // 
到达空树时停止递归遍历
        if (t == NULL)
               return NULL;
        // 
自底向上构造新树:先构造两个子树,然后构造父节点。
        // 
在节点t,生成左子树的副本,将其根节点指针赋值给newLeft
        newLeft = copyTree(t->left);
        // 
生成右子树的副本,将其根节点指针赋值给newRight
        newRight = copyTree(t->right);
        // 
生成新节点,其节点值与t的值相同,其子节点是被复制的t的子树
        newNode = new BTNode<T> (t->data, newLeft, newRight);
        // 
返回新复制的树的根节点的指针
        return newNode;
}
 
template <typename T>
void  BTree<T>::deleteTree(BTNode<T> *t)
{
        // 
后序遍历,删除t的左、右子树,然后删除节点t
        if (t != NULL)
        {
               deleteTree(t->left);
               deleteTree(t->right);
               delete t;
        }
}
 
template <typename T>
void  BTree<T>::clearTree(BTNode<T> * & t)
{
        deleteTree(t);
        t = NULL//
此时根为NULL
}
 
template <typename T>
void BTree<T>::displayTree(const BTNode<T> *t, const int dataWidth/* =1 */,const int screenWidth/* =64 */)
{
        // 
存储每个节点的队列
        queue<BTNode<T> *> q;
        //
存放节点打印信息的队列;
 
        queue<Info>QI;
        BTNode<T> *currNode;
        Info currInfo;
        int units (screenWidth/dataWidth);
        int offset = units/2;
        //
当前节点的列坐标
        int currlevel = -1;
        //
当前节点的同层的前一节点的行坐标
        int preX;
 
        //
如果树为空,退出
        if (t == NULL)
               return;
        // 
在队列q中插入根节点来初始化队列
        q.push(t);
        //
在队列QI中插入根节点坐标初始化队列
        QI.push(Info(offset,0));
        // 
继续迭代过程,直到队列空
        while(!q.empty())
        {
               // 
从队列中删除前端节点,并访问节点
               currNode = q.front();
               q.pop();
               currInfo = QI.front();
               QI.pop();
               if( currInfo.yLevel != currlevel )
               {
                       //
换两行
                       cout<<"/n/n" ;
                       //
新行,起始位置为0
                       preX = 0;
                       //
子女节点的偏移量为 上层节点的1/2
                       offset /= 2;
                       //
更新当前节点坐标层次
                       currlevel = currInfo.yLevel;
               }
 
               //
在相应位置输出节点队列头部元素的值,类型为T
               //
我们假定类型T定义了合适的<<操作符
               cout<<setw((currInfo.xIndent-preX)*dataWidth)
                       <<currNode->data;
 
               if( currNode->left != NULL )
               {
                       //
左子节点入队
                       q.push(currNode->left) ;
                       //
左子节点位置信息入队
                       QI.push(Info(currInfo.xIndent-offset,currInfo.yLevel+1));
               }
               if( currNode->right != NULL )
               {
                       //
右子节点入队
                       q.push(currNode->right) ;
                       //
右子节点位置信息入队
                       QI.push(Info(currInfo.xIndent+offset,currInfo.yLevel+1));
               }
               preX = currInfo.xIndent;
        } //while
循环
}
 
template<typename Type>
BTNode<Type>* BTree<Type>::Find(const Type item) const{
        BTNode<Type> *pstart=root;
        while(pstart){
               if(item==pstart->data){
                       return pstart;
               }
               if(item<pstart->data){
               pstart=pstart->left;   //if less than the node then find in the left subtree
               }
               else{
                       pstart=pstart->right;//if more than the node then find in the right subtree
               }
        }
        return NULL;
}
 
template<typename Type>
bool operator==(const BTree<Type> s,const BTree<Type> t){
        return equal(s.root,t.root);
}
 
#endif
 
//Main.cpp

 #include "BTNode.h"
#include "BTree.h"
#include <iostream>
using namespace std;
 
//
遍历算法的visit函数,输出节点数据值
 
void printChar(char& elem)
{
string seperator = "  ";
cout <<  elem << seperator;
}
 
BTNode<char> *makeCharTree();
 
int main()
{
       const int charWidth=1;
       const int ScreenWidth=64;
       //
任何自己想要完成的操作
       cout<<"按回车键结束程序:" << endl;
       cin.get();
       return 0;
}

 

 

 
 
 
 
 

 [r1]注意:这个文件并没有完全组织好,我们可以利用类来完成。在这个BTNode私有成员里面添加二叉树的类为友元类。这样就ok啦、但是别忘记了,在添加友元的时候要声明一下二叉树类哦。另外提示一下:模板的定义和实现必须在一个文件里面。这个所有的编译器都是这么求的、其中第三个程序是把前2个结合在一起的。
 [r2]其实这里完全可以把成员设置为私有的。然后利用公有的const GetValue();函数来实现
 [r3]关于这个头文件的说明可以ctrl+左键点击此处的链接查看
 [r4]里头定义了一些附带类型。
 

比如

std::size_t 无符号INT
std::ptrdiff_t 有符号INT用于保存随机访问迭代器的的差值。
这是一个C文件的C++版本文件;
假如你用原版本stddef.h的话就不用std::.
 
 [r5]在层次遍历的时候用到了队列。而之前的三种遍历只是调用递归实现。其实也可以用非递归的方式实现,注意这个层次遍历
 [r6]注意,在计算二叉树的深度的时候只能用后续遍历算法。因为必须从下往上算起。
 [r7]用的也是后续遍历算法
 [r8]删除树的时候也必须从下往上,所以也是后续遍历。而且必须是。
 [r9]此处提示我们可以在类中在私有成员中添加一个结构体或者类来作为成员。
 [r10]这个函数用来在屏幕上直观的打印树、
 [r11]这个文件也是二叉树的实现。但是这个相对于上面的那个来说更加的适合新手。更加的规范。我们可以结合起来。
 [r12]添加为公开的友元类,。其实我们也可以添加为私有的。
 [r13]这个程序算是完美的。几何前2个。以后用到的时候可以套用、。
 说明一点,我的这个函数查找结点查找节点和获取双亲节点的算法有一些问题,因为那个急于排序之后的,比如二叉搜索树可以那样。对于二叉树逻辑不是很严密,我推荐用层次遍历来进行查找,另外,很多人都对于这个二叉树的创建很头疼,其实这个我一般用的是层次创建。具体的算法实现网上有,所以此粗话就不发了。