#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