二叉樹模板

         普通二叉樹模板,編碼至二叉樹遍歷,測試程序給出了遍歷目錄(並拷貝)的一個應用示例。
 
注:
        1、編譯測試環境:vs2005+boost
 
====================================================================
#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_

#include <boost/throw_exception.hpp>

#define EN_TEST_BTR
#ifdef EN_TEST_BTR
#include <boost/lexical_cast.hpp>
#include <io.h>
#include <iostream>
#include <direct.h>
#include <fstream>
#include <string>
#endif

namespace redwolf
{
    template <typename T> class btr;

    //==================btr_node================
    template <typename T>
    class btr_node{
    public:
    protected:
    private:
  btr_node(const T& item=T(), btr_node<T>* _ln=NULL, btr_node<T>* _rn=NULL):element(item), _l(_ln), _r(_rn){}

  T element;
  btr_node<T>* _l;
  btr_node<T>* _r;
  friend class btr<T>;
    };

    //==================用於遍歷樹的函數對象模板================
    //可接受的對象形式:
    //1、重載void operator() (X& x)的函數對象;
    //2、形如void (*f)(X& x)函數指針.
    //更一般的形式仍在探索中
    template <typename X>
    class btrvisit_base
    {
    public:

    virtual void operator() (X& x)=0;

    virtual btrvisit_base<X>*  clone() const=0;

    virtual ~ btrvisit_base(){}

    protected:
    private:
    };//純虛基類

    template <typename F, typename X>
    class btrvisit_f : public btrvisit_base<X>
    {
    public:

  btrvisit_f(F f0):f(f0){}

  btrvisit_f(const btrvisit_f<F, X>& other):f(other.f){}

  virtual void operator() (X& x){
      return f(x);
  }

  virtual btrvisit_base<X>* clone() const{
      return new btrvisit_f<F, X>(*this);
  }

    protected:
    private:
  F f;
    };

    //==================btr================
    template <typename X>
    class btr_visitor
    {
    public:
  //模板構造函數c++1994年批准的規範(《C++沉思錄》page249)
  template <typename F> btr_visitor(F f)
    :_p(new btrvisit_f<F, X>(f)){}

  //拷貝構造  
      btr_visitor(const btr_visitor<X>& other):_p(other._p->clone()){}

  //重載=
  virtual btr_visitor& operator= (const btr_visitor& rhs){
      if(&rhs!=this)
      {
    delete _p;
    _p=rhs._p->clone();
      }
      return *this;
  }

  //重載()
  virtual void operator() (X& x) const{
      return _p->operator ()(x);
  }

  //析構  
  virtual ~btr_visitor(){
      delete _p;
  }

    protected:
    private:
  btrvisit_base<X>* _p;
    };

    template <typename T>
    class btr
    {
    public:
  //無參構造
  btr():_root(NULL){}
  
  //構造1
  btr(const T& item):_root(new btr_node<T>(item)){}//no throw  
  
  //構造2
  btr(const T& item, const btr<T>& lt, const btr<T>& rt):_root(new btr_node<T>(item)){
      attach_left_subtree(lt);
      attach_right_subtree(rt);
  }//no throw

  //拷貝構造
  btr(const btr<T>& tr):_root(NULL){
      copy_tree(_root, tr._root);
  }

  //析構,使用了shared_ptr,不用在此釋放實際指針
  virtual ~btr(){
      destroy_tree(_root);
  }

  //重載=
  virtual btr<T>& operator=(btr<T>& rhs){
      if(&rhs!=this)
      {
    destroy_tree(_root);
    copy_tree(_root, rhs._root);
      }  
      return *this;
  }

  //判斷一棵樹是否爲空樹
  virtual bool empty() const{
      return (_root==NULL);
  }

  //獲取根節點數據元素
  virtual T get_root_date() const{
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));
      return _root->element;
  }

  //設置根結點數據元素
  virtual void set_root_data(const T& item){
      if(empty())
      {
    _root=new btr_node<T>(item);
    if(_root==NULL) boost::throw_exception("memory unenough.");
      }
      else _root->element=item;
  }

  //在非空的、無左子樹的樹上生成一個左子樹
  virtual void attach_left(const T& item){
      if(empty())
    boost::throw_exception(std::bad_cast("Empty Tree!"));
      if(_root->_l!=NULL)
    boost::throw_exception(std::bad_cast("Can't attach left!"));

      _root->_l=new btr_node<T>(item);
      if(_root->_l==NULL) boost::throw_exception("memory unenough.");
  }

  //在非空的、無右子樹的樹上生成一個右子樹
  virtual void attach_right(const T& item)
  {
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));
      if(_root->_r!=NULL)
    boost::throw_exception(std::bad_cast("Can't attach right!"));

      _root->_r=new btr_node<T>(item);
      if(_root->_r==NULL) boost::throw_exception("memory unenough.");
  }

  //在非空的、無左子樹的樹上掛接一個左子樹
  virtual void attach_left_subtree(const btr<T>& lt){
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));
      if(_root->_l!=NULL)  
    boost::throw_exception(std::bad_cast("Can't attach left sub tree!"));
    
      if(this!=<)
    copy_tree(_root->_l, lt._root);
  }

  //在非空的、無右子樹的樹上掛接一個右子樹
  virtual void attach_right_subtree(const btr<T>& rt){
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));
      if(_root->_r!=NULL)
    boost::throw_exception(std::bad_cast("Can't attach right sub tree!"));
    
      if(this!=&rt)
    copy_tree(_root->_r, rt._root);
  }

  //摘除樹的左子樹,左子樹由lt輸出
  virtual void detach_left_subtree(btr<T>& lt){
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));
    
      lt=btr<T>(_root->_l);
      destroy_tree(_root->_l);
  }

  //摘除樹的右子樹,右子樹由rt輸出
  virtual void detach_right_subtree(btr<T>& rt){
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));

      rt=btr<T>(_root->_r);
      destroy_tree(_root->_r);
  }

  //獲取樹的左子樹
  virtual btr<T> get_left_subtree() const{
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));
      if(_root->_l!=NULL)
    return btr<T>(_root->_l);
      else
    return btr<T>();
  }

  //獲取樹的右子樹
  virtual btr<T> get_right_subtree() const{
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));

      if(_root->_r!=NULL)
    return btr<T>(_root->_r);
      else
    return btr<T>();
  }

  //獲取樹根的孩子節點指針(指針內容均只讀)
  virtual void get_child_ptrs(btr_node<T> const *& lnode,  
      btr_node<T> const *& rnode)const{
      lnode=_root->_l;
      rnode=_root->_r;
  }

  //獲取根節點
  virtual btr_node<T>* get_root_ptr() const{
      return _root;
  }
  
  //設置根節點  
  virtual void reset_root_ptr(btr_node<T>* _newroot=NULL){
      _root=_newroot;
  }

  //銷燬樹
  virtual void destroy(){
      destroy_tree(_root);
  }

  //前序遍歷樹
  virtual void pre_order_traverse(btr_visitor<T>& v){
      pre_order(_root, v);
  }

  //中序遍歷樹
  virtual void in_order_traverse(btr_visitor<T>& v){
      in_order(_root, v);
  }
  
  //後序遍歷樹
  virtual void post_order_traverse(btr_visitor<T>& v){
      post_order(_root, v);
  }

  //針對特定對象的實現,應該拿到外面去。
  //此函數即是,它針對文件拷貝,這裏主要做測試用。
  void get_last_appended_subtree(btr<T>& null_tree)
  {
      if(empty())
    boost::throw_exception(std::bad_cast("Empty tree!"));

      null_tree.destroy();
      btr<T>& tr=*this;
      btr_node<T>* _lp=NULL, *_rp=NULL;
      tr.get_child_ptrs(tr._root, _lp, _rp);
      if(_lp!=NULL)
      {
    btr<T> child;
    child.reset_root_ptr(_lp);
    child.get_last_appended_subtree(null_tree);
    child.reset_root_ptr();
    return;
      }
      else if(_rp!=NULL)
      {
    btr<T> child;
    child.reset_root_ptr(_rp);
    child.get_last_appended_subtree(null_tree);
    child.reset_root_ptr();
    return;
      }
      else
      {
    null_tree.reset_root_ptr(tr._root);  
    return;
      }
      }
  
    protected:

  //構造3
  btr(btr_node<T>* _node){
      copy_tree(_root, _node);
  }

  //拷貝一棵樹
  void copy_tree(btr_node<T>*& newnode, btr_node<T>* const _node){
      if(_node!=NULL)
      {
    newnode=new btr_node<T>(_node->element);
    if(newnode==NULL) boost::throw_exception("memory unenough.");
    copy_tree(newnode->_l, _node->_l);
    copy_tree(newnode->_r, _node->_r);
      }
  }
  //銷燬一棵樹
  void destroy_tree(btr_node<T>*& node){
      if(node!=NULL)
      {
    destroy_tree(node->_l);
    destroy_tree(node->_r);
    delete node;
    node=NULL;
      }
  }
  
  //獲取樹的子節點
  void get_child_ptrs(btr_node<T>* _node,
      btr_node<T>*& lnode,
      btr_node<T>*& rnode)const{
      lnode=_node->_l;
      rnode=_node->_r;
  }
  
  //設置樹的子節點
  void set_child_ptrs(btr_node<T>* _node, const btr_node<T>* _lnode, const btr_node<T>* _rnode){
      _node->_l=_lnode;
      _node->_r=_rnode;
  }
  
  //前序
  void pre_order(btr_node<T>* _node, btr_visitor<T>& v){
      if(_node!=NULL)
      {
    v(_node->element);
    pre_order(_node->_l, v);
    pre_order(_node->_r, v);
      }
  }
  
  //中序
  void in_order(btr_node<T>* _node, btr_visitor<T>& v){
      if(_node!=NULL)
      {
    in_order(_node->_l, v);
    v(_node->element);
    in_order(_node->_r, v);
      }
  }
  
  //後序
  void post_order(btr_node<T>* _node, btr_visitor<T>& v){
      if(_node!=NULL)
      {
    post_order(_node->_l, v);
    post_order(_node->_r, v);
    v(_node->element);
      }
  }

    private:
  btr_node<T>* _root;
    };

#ifdef EN_TEST_BTR
    using namespace std;

    void cvisit(string& v)
    {
  printf("cvisit: [%s]\n", v.c_str());
    }

    class visit{
    public:
  visit(){}

  virtual void operator() (string& item){
      std::cout<<"visit: visit item."<<endl;
  }

    protected:

    private:

    };

    class my_visit : public visit
    {
    public:
  my_visit(){}

  virtual void operator() (string& item){
      std::cout<<"my_visit: visit item. [ "<<item<<" ]"<<endl;
  }

    protected:
    private:
    };

    class dirvisit : public visit
    {
    public:
  dirvisit(){}

  virtual void operator() (string& v){
      std::string dStr=v.substr(2, v.size()-2);
      dStr="D:\\Copy"+dStr;
      if(v.rfind(".")==string::npos)//不帶後綴的認爲是目錄,僅供測試
      {
    std::cout<<"Make dir: [ "<<dStr.c_str()<<" ]"<<endl;
    _mkdir(dStr.c_str());
      }
      else
      {
    std::cout<<"Copy file: [ "<<dStr.c_str()<<" ]"<<endl;
    FILE* pf0=NULL;
    pf0=fopen(v.c_str(), "rb");
    if(pf0==NULL) return;
    std::ifstream in(pf0);
    in.seekg(0,ios::end);
    unsigned int size=0;
    size=in.tellg();
    char* buf=new char[size];
    in.seekg(0, ios::beg);
    in.read(buf, size);
    FILE* pf1=NULL;
    pf1=fopen(dStr.c_str(), "wb");
    if(pf1==NULL) return;
    std::ofstream out(pf1);
    out.write(buf, size);
    delete[] buf;
    buf=NULL;
    in.close();
    out.close();
      }
  }

    protected:
    private:
    };

    void test0()
    {
  btr<string> t0("000"), t1, t2, t3, t4("0"), t5("1"), t6("2"), t7, t8, t100;
  t0.attach_left("111");
  t0.attach_right("222");
  t100=t2=t1=t0;
  t0=t0.get_left_subtree();
  t1.detach_left_subtree(t3);
  t2.detach_left_subtree(t2);
  t0=t1=t2=t3=t100;

  cout<<"t0: "<<t0.get_root_date()<<endl;
  t0.set_root_data("001");
  cout<<"t0: "<<t0.get_root_date()<<endl;
  cout<<"t1: "<<t1.get_root_date()<<endl;
  cout<<"t2: "<<t2.get_root_date()<<endl;

  cout<<"==============t4============="<<endl;
  t4.attach_left_subtree(t0);
  t4.attach_right_subtree(t1);
  my_visit visit;
  btr_visitor<string> visitor(visit);
  t4.pre_order_traverse(visitor);

  cout<<"==============t5============="<<endl;
  t5.attach_left_subtree(t4);
  t5.attach_right_subtree(t2);
  t5.pre_order_traverse(visitor);

  cout<<"==============t6============="<<endl;
  t6.attach_left_subtree(t4);
  t6.attach_right_subtree(t5);
  t6.pre_order_traverse(visitor);

  int i=0;
  t7.set_root_data("0");
  while(i<5)
  {
      t7.get_last_appended_subtree(t8);
      if((i%2))
    t8.attach_left(boost::lexical_cast<string>(i+1));
      else
    t8.attach_right(boost::lexical_cast<string>(i+1));

      t8.reset_root_ptr();
      i++;
  }
  cout<<"==============t7============="<<endl;
  btr_visitor<string> visitor1(cvisit);
  t7.pre_order_traverse(visitor1);
    }

    void   filesearch(string path, redwolf::btr<string>& tr)    
    {  
  struct _finddata_t filefind;
  string   curr=path+"\\*.*";  
  int   done=0,handle;    
  if((handle=(int)_findfirst(curr.c_str(),&filefind))==-1) return;  

  redwolf::btr<string> null_tree;
  while(!(done=_findnext(handle,&filefind)))    
  {      
      if((_A_SUBDIR==filefind.attrib))    
      {      
    if(filefind.name[0]=='.') continue;
    std::cout<<path<<"\\"<<filefind.name<<endl;
    tr.get_last_appended_subtree(null_tree);
    null_tree.attach_left(path+"\\"+filefind.name);
    null_tree.reset_root_ptr();
    filesearch(path+"\\"+filefind.name, tr);
      }    
      else      
      {    
    std::cout<<path<<"\\"<<filefind.name<<endl;
    tr.get_last_appended_subtree(null_tree);
    null_tree.attach_right(path+"\\"+filefind.name);
    null_tree.reset_root_ptr();
      }  
  }        
  _findclose(handle);    
    }

    void dirtest()
    {
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

  const std::string s0="d:\\", s1="OC";
  std::string pathname=s0+s1;

  cout<<endl;
  cout<<"==============dir_copy_test============="<<endl;
  cout<<endl;
  redwolf::btr<string> ocTree(pathname);
  filesearch(pathname, ocTree);
  printf("===============================\n");
  printf("Copy files:");
  printf("===============================\n");
  _mkdir("d:\\copy");
  dirvisit visit;
  btr_visitor<string> visitor(visit);
  ocTree.pre_order_traverse(visitor);
    }
#endif

};

#endif
====================================================================
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章