二叉树完整实现C++

来源:互联网 发布:中文域名注册查询 编辑:程序博客网 时间:2024/06/05 18:43

总结网上一位大牛写的代码,看看人家,就写一个二叉树,就把C++继承多态的作用发挥出来,看咱只能简单定义一个class, 差距大啊~自己还是小白~

BinaryTree.h
#ifndef BINARY_TREE#define BINARY_TREE#include <iostream>#include <string>#include <stdexcept>#include <stack>using namespace std;enum ChildID{LEFTCHILD = 0, RIGHTCHILD};//子节点类型,左节点or右节点;template<class T> class BinaryTree;template<class T> class BTreeNode{friend class BinaryTree<T>;public:BTreeNode(): pParent(0), pLChild(0), pRChild(0){}BTreeNode(T elem, BTreeNode<T>* parent=0, BTreeNode* lchild=0, BTreeNode* rchild=0):pParent(parent),pLChild(lchild),pRChild(rchild),data(elem) {}T GetData() const; //获取节点数据;T& GetDataRef();         //不应当提供这样的接口,这里仅仅让iterator能够自由访问存储的数据;BTreeNode* GetParent() const;//获取节点的父节点BTreeNode* GetLChild() const;//获取节点的左孩子节点BTreeNode* GetRChild() const;//获取节点的右孩子节点void SetData(const T& elem );//修改节点的数据;/*下面是更改节点的指针域结构的function,是否真的需要,还得仔细考量做为树的节点,一般不允许直接访问节点中的指针数据,如果这些数据在树被建立完成以后修改,会破坏树的结构;*/void SetParent( BTreeNode<T>* parent, ChildID CHID ); //设置当前节点的父节点,并指定当前节点作为子节点的类型;void SetLeft( BTreeNode<T>* left);                 //设置当前节点的左子节点;void SetRight( BTreeNode<T>* right);               //设置当前节点的右子节点;private:BTreeNode<T>* pParent;BTreeNode<T>* pLChild;BTreeNode<T>* pRChild;T data;};//declare BTreeNode end//*********************************************************// BTreeNode Implementation//*********************************************************template<class T> T BTreeNode<T>::GetData() const{ return data;}template<class T>T& BTreeNode<T>::GetDataRef(){ return data;}template<class T>T BTreeNode<T>::GetParent() const{ return pParent;}template<class T>T BTreeNode<T>::GetRChild() const{ return pRChild;}template<class T>T BTreeNode<T>::GetLChild() const{ return pLChild;}template<class T>T BTreeNode<T>::SetData(const T& elem){ data = elem;}template<class T>void BTreeNode<T>::SetParent(BTreeNode<T>* parent, ChildID CHID ){if(!parent) return;if(CHID==LEFTCHILD) //当前节点作为parent的左子节点;{pParent = parent;parent->pLChild = this;}else if (CHID==RIGHTCHILD){pParent = parent;parent->rLChild = this;}}template<class T>void BTreeNode<T>::SetLeft(BTreeNode<T>* left){ pLChild=left; }template<class T>void BTreeNode<T>::SetRight(BTreeNode<T>* right){ pRChild=right; }// BTreeNode Implementation over//*********************************************************//*********************************************************template<class T> class BinaryTree{public:BinaryTree() : root(NULL){}BinaryTree( T value) : RefValue(value), root(NULL) {}BinaryTree( const BinaryTree<T>& tree);                 //copy ConstruBcture privatedBinaryTree<T>& operator=(const BinaryTree<T>& tree); //operator= privatedvirtual ~BinaryTree();virtual int IsEmpty(){return root==NULL;}/*    * 下面三个函数的可用性,返回值类型的正确性值得考量    * 这样做不仅会破坏树的结构,而且很容易引起内存泄漏    * 在一般的树中最好不要提供这三个接口 ;    */virtual BTreeNode<T>* Parent( BTreeNode<T>* current ); //返回所给结点父结点;virtual BTreeNode<T>* LeftChild( BTreeNode<T>* current);      //返回节点的左孩子;virtual BTreeNode<Ty>* RightChild( BTreeNode<T>* current);     //返回节点的右孩子;virtual bool Insert( const T& item);        //插入元素;virtual bool Find( const T& item) const;    //搜索元素;const BTreeNode<T>* GetRoot() const;      //取树根;//遍历操作void PreOrder() const;   //前序;void InOrder() const; //中序;void PostOrder() const;  //后序;//二叉树特性操作函数int Size() const;int Size( const BTreeNode<T>* troot) const;int Height() const;int Height( const BTreeNode<T>* troot) const;bool operator==( const BinaryTree<T>& tree) const;//下面的接口是以不同的方式来构建二叉树BinaryTree<T>& AutoCreateTree(const std::string& expstr);            //自动判断格式并建立BinaryTree<T>& PreOrderCreateTree(const std::string& expstr);        //先序建立BinaryTree<T>& PostOrderCreateTree(const std::string& expstr);       //后续建立protected:BTreeNode< T>* Parent( BTreeNode<T>* start, BTreeNode<T>* current );int Insert( BTreeNode<T>* current, const T& item);void Travers( BTreeNode<T>* current, std::ostream& out ) const;void Find( BTreeNode<T>* current, const T& item ) const;void destroy( BTreeNode<T>* current);  //遍历递归void InOrder( BTreeNode<T>* current) const;void PreOrder( BTreeNode<T>* current ) const;void PostOrder( BTreeNode<T>* current) const;//二叉树特性递归操作函数BTreeNode<T>* Copy( BTreeNode<T>* troot, BTreeNode<T>* parent);bool equal( BTreeNode<T>* troot1, BTreeNode<T>* troot2) const;//建树用的递归函数BTreeNode<T>* PreOrderCreateNode(const char* &expstr, BTreeNode<T>* parent);    //先序递归建立二叉树BTreeNode<T>* PostOrderCreateNode(const char* &expstr, BTreeNode<T>* parent);    //后续递归建立二叉树//声明一组用于二叉树的迭代器iteratorprivate:class iterator;       //迭代器基类friend class iterator;public:class PreOrder_iterator; //前序迭代器class InOrder_iterator;     //中序迭代器class PostOrder_iterator;   //后序迭代器class LevelOrder_iterator;  //层序迭代器friend class PreOrder_iterator;friend class InOrder_iterator;friend class PostOrder_iterator;friend class LevelOrder_iterator;private:BTreeNode< T >* root;     //树的根指针  T RefValue;              //数据输入终结标志};//END BinaryTree/********************************** * implament of template BinaryTree  *  **********************************/template <class T> BinaryTree<T>::BinaryTree( const BinaryTree<T>& tree)   //copy Constructor{root = Copy(tree.root, NULL);}template <class T> BinaryTree<T>& BinaryTree<T>::operator=( const BinaryTree<T>& tree)     //operator= constructor{destroy(root);root = Copy(tree.root, NULL);return *this;}template <class T> BinaryTree<T>::~BinaryTree(){destroy(root);              //遍历删除二叉树}template <class T> bool BinaryTree<T>::Insert( const T& item){return true;}template <class T>bool BinaryTree<T>::Find( const T& item) const{return true;} template <class T>BTreeNode<T>* BinaryTree<T>::Parent( BTreeNode<T>* current){if( root == NULL || root == current ){return NULL;}else{return current->pParent;}/*    * 由于节点保留了parent的地址,所以可以直接取得父节点的地址    * 但是节点中如果没有parent的数据,就必须调用递归查询来寻找父节点的地址    * 代码片断如下,它调用了Parent( BTreeNode<T> *start, BTreeNode<T>* current)      return (root == NULL || root == current) ? NULL : Parent( root, current);          */   }template <class T>BTreeNode<T>* BinaryTree<T>::LeftChild( BTreeNode<T>* current){return current != NULL ? current->pLChild : NULL;}template <class T>BTreeNode<T>* BinaryTree<T>::RightChild( BTreeNode<T>* current){return current != NULL ? current->pRChild : NULL;  }template <class T>BTreeNode<T>* BinaryTree<T>::Parent( BTreeNode<T> *start, BTreeNode<T>* current){//从结点start开始,搜索节点current的父结点,//如果找到其父节点,则函数将其返回,否则返回 NULLif( !start ) return NULL;if( start->pLChild == current || start->pRChild == current) return start;BTreeNode<T> *pNode;if((pNode = Parent( start->pLChild, current)) != NULL) {return pNode;      }                                 else {return Parent( start->pRChild, current);  }                              }template <class T> const BTreeNode<T>* BinaryTree<T>::GetRoot() const{return root;}template <class T>void BinaryTree<T>::Travers( BTreeNode<T>* current, std::ostream& out) const {//前序输出根为current的二叉数if( current ) {out << current->data;Travers( current->pLChild , out );Travers( current->pRChild, out );}else{out<<"#";}}//中序遍历操作template <class T>void BinaryTree<T>::InOrder() const {std::cout << "InOrder Traval Tree:/n";InOrder( root );std::cout << std::endl;     }template <class T>void BinaryTree<T>::InOrder( BTreeNode<T>* current) const{//递归私有函数,中序遍历二叉树if(current != NULL) {InOrder(current->pLChild);std::cout << current->data;     InOrder(current->pRChild);   }  else {std::cout << "#";}}//前序遍历操作template <class T>void BinaryTree<T>::PreOrder() const {std::cout << "PreOrder Travel Tree:/n";PreOrder (root);std::cout << std::endl;  }template <class T>void BinaryTree<T>::PreOrder( BTreeNode<T>* current) const{if(current != NULL) {std::cout << current->data;PreOrder(current->pLChild);PreOrder(current->pRChild);}else{std::cout <<"#";}}//后序遍历操作template <class T>void BinaryTree<T>::PostOrder() const {//后序遍历std::cout << "PostOrder Travel Tree:/n";PostOrder(root);std::cout << std::endl;  }template <class T>void BinaryTree<T>::PostOrder( BTreeNode<T>* current) const{//后序递归操作if( current != NULL ) {PostOrder(current->pLChild);PostOrder(current->pRChild);std::cout << current->data;}else{std::cout << "#";}}//计算二叉树的结点数template <class T>int BinaryTree<T>::Size() const {   return Size(root);} template <class T>int BinaryTree<T>::Size( const BTreeNode<T>* troot) const {   if(troot == NULL)  return 0;   //空树,返回0   else return 1 + Size(troot->pLChild) + Size(troot->pRChild);   } //计算二叉树的高度template <class T>int BinaryTree<T>::Height() const{   return Height(root);} template <class T>int BinaryTree<T>::Height( const BTreeNode<T>* troot) const {   if ( troot == NULL ) return -1;   else return 1 + MAX( Height( troot->pLChild ) , Height( troot->pRChild) );} //递归拷贝的私有函数;template <class T>BTreeNode<T>* BinaryTree<T>::Copy( BTreeNode<T>* troot, BTreeNode<T>* parent) {   if (NULL == troot) return NULL;      BTreeNode<T>* pNode = new BTreeNode<T>;   pNode->data = troot->data;                          //拷贝数据   pNode->pParent = parent;   pNode->pLChild = Copy( troot->pLChild, pNode );        //新建左子树   pNode->pRChild = Copy( troot->pRChild, pNode );        //新建右子树   return pNode;                                     //返回树根结点} //判断二叉树内容是否相等template <class T>bool BinaryTree<T>::operator==( const BinaryTree<T>& tree) const {   return equal( root, tree.root );} //判断二叉树相等的递归操作template <class T>bool BinaryTree<T>::equal( BTreeNode<T>* troot1, BTreeNode<T>* troot2) const {   if( NULL == troot1 && NULL == troot2 ) return true;   if( (NULL == troot1 && NULL != troot2)      || (NULL != troot1 && NULL == troot2)      || (troot1->data != troot2->data) )  {      return false;   }   else {   return equal( troot1->pLChild, troot2->pLChild) &&   equal( troot1->pRChild, troot2->pRChild);   }   return true;} template <class T> void BinaryTree<T>::destroy( BTreeNode<T>* current) {   if( current ) {      destroy( current->pLChild );    //递归删除左结点      destroy( current->pRChild);     //除右节点      delete current;      current = NULL;                //空置指针   }} //define of Max functiontemplate <class _T>_T MAX(const _T& a, const _T& b){   return (a>=b) ? a : b;   } //*********************************************************//1:先序方式建立二叉树 template <class T>BinaryTree<T>& BinaryTree<T>::PreOrderCreateTree(const std::string& expstr){   using namespace std;      const char* exp = expstr.c_str();   if(*exp != '#')    //以#开头表示字符串不是先序表达式   {      destroy(root);      root = PreOrderCreateNode(exp, NULL);      }   else   {      cout << "Your string expression error, I can't Create B-Tree :)/n";   }      return *this;   } template <class T>BTreeNode<T>*BinaryTree<T>::PreOrderCreateNode(const char* &expstr, BTreeNode<T>* parent){   if( *expstr == '#' || *expstr == '/0') return NULL;   BTreeNode<T>* pnewNode = new BTreeNode<T>(*expstr, parent);      assert(pnewNode);      pnewNode->pLChild = PreOrderCreateNode(++expstr, pnewNode);   pnewNode->pRChild = PreOrderCreateNode(++expstr, pnewNode);   return pnewNode;} //********************************************************* //********************************************************* //3:后续方式建立二叉树template <class T>BinaryTree<T>& BinaryTree<T>::PostOrderCreateTree(const std::string& expstr){   using namespace std;   const char* exp = expstr.c_str();   if( expstr.size() < 3)   {      destroy(root);      return *this;   }         if(*exp == '#' && *(exp+1) == '#' && *(exp+2) == '#' )     //以 ##'X' 开头表示字符串是后续序表达式 'X'表示元素   {      destroy(root);      exp += expstr.size()-1;      root = PostOrderCreateNode(exp, NULL);      //反向遍历生成   }   else   {      cout << "Your string expression error, I can't Create B-Tree :)/n";   }      return *this;   } template <class T>BTreeNode<T>*BinaryTree<T>::PostOrderCreateNode(const char* &expstr, BTreeNode<T>* parent){   if( *expstr == '#') return NULL;   BTreeNode<T>* pnewNode = new BTreeNode<T>(*expstr, parent);      assert(pnewNode);   pnewNode->pRChild = PostOrderCreateNode(--expstr, pnewNode);      pnewNode->pLChild = PostOrderCreateNode(--expstr, pnewNode);      return pnewNode;}  //********************************************************//********************************************************//三种迭代器的实现 //iterator 是私有的基类迭代器,这里没有实现常量树的迭代器 const_iterator//这样做确保了用户不可能访问到这个迭代器template <class T>class BinaryTree<T>::iterator {public:   iterator():m_btree(NULL), pCurrent(NULL){}   virtual ~iterator() {}      virtual iterator& operator= (const iterator& iter)    {       pCurrent = iter.pCurrent;      return *this;   }      virtual iterator& GotoFirst() = 0;      //游标索引到第一个节点   virtual bool IsEnd() = 0;               //游标是否已经索引到末尾      virtual iterator& operator++() = 0;         // 游标自增   //virtual iterator operator++(int) = 0;      virtual const T& current() const;   virtual T& operator*();   virtual T* operator->();protected:   BinaryTree<T>* m_btree;   BTreeNode<T>* pCurrent; }; template <class T>const T& BinaryTree<T>::iterator::current() const {   if(pCurrent != NULL)   {      return pCurrent->GetDataRef();   }   else   {      throw std::out_of_range("iterator error/n");   }} template <class T>T& BinaryTree<T>::iterator::operator*(){   if(pCurrent != NULL)   {      return pCurrent->GetDataRef();   }   else   {      throw std::out_of_range("iterator error/n");   }  } template <class T>T* BinaryTree<T>::iterator::operator->(){   if(pCurrent != NULL)   {      return &(pCurrent->GetDataRef());   }   else   {      throw std::out_of_range("iterator error/n");   }        } //*********************************************************//这里采用两种方式来遍历树//1:采用简单计数栈的非递归遍历(要求结点中有父节点数据域)//2:采用栈的非递归遍历(在最后注释部分)//*********************************************************  //前序遍历迭代器(无栈) template <class T>class BinaryTree<T>::PreOrder_iterator : public iterator {   using iterator::pCurrent;   using iterator::m_btree;public:   PreOrder_iterator() {}   PreOrder_iterator(const BinaryTree<T>& tree )   {      m_btree = const_cast< BinaryTree<T>* >(&tree);      GotoFirst();//索引至第一个结点;     }      PreOrder_iterator(const PreOrder_iterator& iter) {      m_btree = iter.m_btree;      pCurrent = iter.pCurrent;   }      PreOrder_iterator& GotoFirst()   {      stk.MakeEmpty();      if(m_btree == NULL)      {         stk.MakeEmpty();         pCurrent = NULL;      }      else      {         pCurrent = const_cast< BTreeNode<T>* >(m_btree->GetRoot());  //强制转换为非常量指针         stk.Push(1);    //记录当前树的根节点访问次数      }   return *this;   }      bool IsEnd()    {      return pCurrent == NULL;     }      PreOrder_iterator& operator++() ;           // 游标自增;   //PreOrder_iterator operator++(int);   private:   stack<int> stk;        //保存访问节点的遍历次数的栈;}; template <class T> BinaryTree<T>::PreOrder_iterator&  BinaryTree<T>::PreOrder_iterator::operator++() //前序后继节点;{   if( stk.IsEmpty() )      //确保迭代器是有效的;   {      return *this;   }      //访问左子节点    if( pCurrent->GetLeft() == NULL) //左节点无效;   {      stk.Pop();      stk.Push(2); //pCurrent 第二次访问;            //查询右节点;      if( pCurrent->GetRight() == NULL)  //右节点也无效;      {         //回溯搜索有效的节点         while( !stk.IsEmpty() && stk.Pop()==2 )          {            pCurrent = pCurrent->GetParent();         }                  stk.Push(1);         //节点的右子节点不可访问,继续回溯,搜索到跟节点,停止搜索;         while(pCurrent != NULL && pCurrent->GetRight() == NULL )         {            pCurrent = pCurrent->GetParent();            stk.Pop();         }                  //如果已经搜索出根节点,抛出异常;         if(pCurrent == NULL)         {            //throw std::out_of_range("BinaryTree iterator over/n");         }         else          {            stk.Pop();            stk.Push(2); //pCurrent访问计数2;                        pCurrent = pCurrent->GetRight();            stk.Push(1);          }      }      else //右节点有效      {         pCurrent = pCurrent->GetRight();         stk.Push(1);      }   }   else  //左节点有效   {      pCurrent = pCurrent->GetLeft();        stk.Push(1);   }   return *this;}  //中序遍历迭代器//InOrder_iterator  template <class T>class BinaryTree<T>::InOrder_iterator : public iterator {   using iterator::pCurrent;   using iterator::m_btree;public:   InOrder_iterator() {}   InOrder_iterator(const BinaryTree<T>& tree )   {      m_btree = const_cast< BinaryTree<T>* >(&tree);      GotoFirst(); //索引至第一个结点      }      InOrder_iterator(const PreOrder_iterator& iter) {      m_btree = iter.m_btree;      pCurrent = iter.pCurrent;   }      InOrder_iterator& GotoFirst()   {      stk.MakeEmpty();      if(m_btree == NULL)      {         stk.MakeEmpty();         pCurrent = NULL;      }      else      {         pCurrent = const_cast< BTreeNode<T>* >(m_btree->GetRoot());         if( pCurrent != NULL )         {            stk.Push(1); //节点计数进1            while( pCurrent->GetLeft() != NULL )            {               pCurrent = pCurrent->GetLeft();                stk.Push(1);                         }                    }      }      return *this;   }         bool IsEnd()    {      return pCurrent == NULL;     }      InOrder_iterator& operator++()           // 游标自增1   {      if(IsEnd())       {         return *this;         }            if( pCurrent->GetRight() == NULL)      {         stk.Pop();         stk.Push(2);         while( !stk.IsEmpty() && stk.Pop() == 2)         {            pCurrent = pCurrent->GetParent();                   }         stk.Push(2);         return *this;      }      else      {         //右节点有效         stk.Pop();         stk.Push(2);         pCurrent = pCurrent->GetRight();         stk.Push(1);                  while( pCurrent->GetLeft() != NULL)         {            pCurrent = pCurrent->GetLeft();            stk.Push(1);                   }      }      return *this;         }   //InOrder_iterator operator++(int);   private:   ChainStack<int> stk;        //保存访问节点的遍历次数的栈 };  //**********************************************************//后序遍历迭代器//PostOrder_iteratortemplate <class T>class BinaryTree<T>::PostOrder_iterator : public iterator {   using iterator::pCurrent;   using iterator::m_btree;public:   PostOrder_iterator() {}   PostOrder_iterator(const BinaryTree<T>& tree )   {      m_btree = const_cast< BinaryTree<T>* >(&tree);      GotoFirst(); //索引至第一个结点      }      PostOrder_iterator(const PreOrder_iterator& iter) {      m_btree = iter.m_btree;      pCurrent = iter.pCurrent;   }      PostOrder_iterator& GotoFirst()   {      stk.MakeEmpty();      if(m_btree == NULL)      {         stk.MakeEmpty();         pCurrent = NULL;      }      else      {         pCurrent = const_cast< BTreeNode<T>* >(m_btree->GetRoot());         if( pCurrent != NULL )         {            stk.Push(1); //节点计数进1            while( pCurrent->GetLeft() != NULL || pCurrent->GetRight() != NULL)            {                if( pCurrent->GetLeft() != NULL)                 {                   pCurrent = pCurrent->GetLeft();                   stk.Push(1);                 }                else if( pCurrent->GetRight() != NULL)                {                   stk.Pop();                   stk.Push(2);                   pCurrent = pCurrent->GetRight();                   stk.Push(1);                }                    }                    }      }      return *this;   }      bool IsEnd()    {      return pCurrent == NULL;     }      PostOrder_iterator& operator++()            // 游标自增1   {      if(IsEnd())       {         return *this;         }            if( pCurrent->GetRight() == NULL || stk.GetTop() ==2)      {         pCurrent = pCurrent->GetParent();         stk.Pop();      }      if( pCurrent != NULL && pCurrent->GetRight() != NULL && stk.GetTop() ==1)         {         //父节点存在右节点,且并未访问过         stk.Pop();         stk.Push(2);         pCurrent =  pCurrent->GetRight();         stk.Push(1);         while( pCurrent->GetLeft() != NULL || pCurrent->GetRight() != NULL)         {            if( pCurrent->GetLeft() != NULL)             {                pCurrent = pCurrent->GetLeft();                stk.Push(1);             }            else if( pCurrent->GetRight() != NULL)            {                stk.Pop();                stk.Push(2);                pCurrent = pCurrent->GetRight();                stk.Push(1);            }         }      }      return *this;         }   private:   ChainStack<int> stk;        //保存访问节点的遍历次数的栈};#endif

 

 

BinaryTree.cpp
#include "BinaryTree.h" #include <iostream> using namespace std; int main(){   BinaryTree<char> tree;      //前序字符串   string str = "ABC#D##E#F##GH#I##JK##L##";      //后续字符串   //string str = "###DC###FEB###IH##K##LJGA";       //前序方法生成二叉树   tree.PreOrderCreateTree(str);    cout << "EXP STR: " << str << endl;      //前序方法遍历打印二叉树   tree.PreOrder();      //中序打印二叉树   tree.InOrder();      //后续打印二叉树   tree.PostOrder();      cout << "Tree Height:" << tree.Height() << endl;   cout << "Tree Height:" << tree.Size() << endl;      //二叉树拷贝构造调用   BinaryTree<char> tree2 = tree;   tree2.PreOrder();       cout << "PreOrder iteraotr!/n";         //二叉树前序迭代器   BinaryTree<char>::PreOrder_iterator preiter(tree2);   while(!preiter.IsEnd())   {            cout << *preiter << ",";      ++preiter;   }   cout << endl;      //二叉树中序迭代器   tree.InOrder();   cout << "InOrder iteraotr!/n";   BinaryTree<char>::InOrder_iterator initer(tree2);   while(!initer.IsEnd())   {            cout << *initer << ",";      ++initer;   }    //二叉树后续迭代器   cout << endl;   tree2.PostOrder();   cout << "PostOrder iteraotr!/n";   BinaryTree<char>::PostOrder_iterator postiter(tree2);    while(!postiter.IsEnd())   {            cout << *postiter << ",";      ++postiter;   }       return 0;}



 

原创粉丝点击