線索二叉樹的中序遍歷
阿新 • • 發佈:2018-12-25
#include<iostream> #include<vector> using namespace std; typedef enum{Link,Thread}PointTag; //Link==0:指標,Thread==1:線索 template<class T> class BiTrNode{ template<class T> friend class BiTrTree; private: T data; BiTrNode *lchild,*rchild; //左右孩子指標 PointTag ltag,rtag; //左右標誌 }; template<class T> class BiTrTree { public: //BiTrTree<T>():elem={}; void InputBiTrNode(); //輸入構成數的結點元素,‘#’表示空串 void Pre_CreateBiTrTree(BiTrNode<T> *&TT); //先序構造二叉樹 void InThreading(BiTrNode<T> *p); //中序遍歷二叉樹 void InOrderThreading(BiTrNode<T> *&Thrt,BiTrNode<T> *TT);//中序遍歷二叉樹T,將其中序線索化,Thrt指向頭結點 void InOrderTraverse_Thr(BiTrNode<T> *TT); //中序遍歷二叉線索樹 void visit(T data); //輸出結點元素 private: vector<T> elem; BiTrNode<T> *pre; }; template<class T> void BiTrTree<T>::InputBiTrNode() { T ch; cout<<"!!!注意:(1)'#'表示空結點;(2)請在輸入的字串末尾加0,作為輸入結束的標誌。"<<endl; while(cin>>ch&&ch!='0') { elem.push_back(ch); //在容器中加入結點元素 }//while }//InputBiTrNode template<class T> void BiTrTree<T>::Pre_CreateBiTrTree(BiTrNode<T> *&TT) { vector<T>::iterator it=elem.begin(); //迭代器it指向elem的開頭 if(it!=elem.end()) { if(*it=='#')//字元為空格,表示結點不存在 { TT=NULL; elem.erase(it); //刪除迭代器it指向的elem中的元素,作用是依次刪除elem的第一個元素 }//if else { if(!(TT=new BiTrNode<T>)) exit(-1); TT->data=*it; //生成根結點 elem.erase(it); //刪除迭代器it指向的elem中的元素,作用是依次刪除elem的第一個元素 Pre_CreateBiTrTree(TT->lchild); //構造左子樹 Pre_CreateBiTrTree(TT->rchild); //構造右子樹 }//else }//if else //此時elem為空,使此時T=NULL;,即結束最初的T的結點的賦值 TT=NULL; }//Pre_CreateBiTrTree template<class T> void BiTrTree<T>::InThreading(BiTrNode<T> *p) { BiTrNode<T> *pt=pre; //用p儲存pre最初的值Thrt if(p) { InThreading(p->lchild); //左子樹線索化 if(!(p->lchild)) { p->ltag=Thread;p->lchild=pre; //前驅線索 }//if else //左子樹不為空,則左孩子標記為指標 p->ltag=Link; if(!(pre->rchild)) { pre->rtag=Thread;pre->rchild=p; //後繼線索 }//if else //右結點指標不為空,則二叉樹T中的結點右結點標誌設定為指標Link型 { if(pre!=pt) //pre是二叉樹T中的結點(不帶頭結點Thrt的二叉樹) pre->rtag=Link; }//else pre=p; //保持pre指向p的前驅 InThreading(p->rchild); //右子樹線索化 }//else }//InOrderThreading template<class T> void BiTrTree<T>::InOrderThreading(BiTrNode<T> *&Thrt,BiTrNode<T> *TT) { //BiTrNode<T> *pre=NULL; if(!(Thrt=new BiTrNode<T>)) exit(-1); Thrt->ltag=Link;Thrt->data=0;Thrt->rtag=Thread; //建立頭結點,左標誌為指標,右標誌為線索 Thrt->rchild=Thrt; //右指標回指,指向自己實現二叉連結串列的迴圈操作if if(!TT) Thrt->lchild=Thrt; //若二叉樹為空,則左指標回指 else { Thrt->lchild=TT;pre=Thrt; InThreading(TT); //中序遍歷進行中序線索化 pre->rchild=Thrt;pre->rtag=Thread; //最後一個結點線索化 Thrt->rchild; }//else }//InOrderThreading template<class T> void BiTrTree<T>::InOrderTraverse_Thr(BiTrNode<T> *TT) { BiTrNode<T> *p=NULL; p=TT->lchild; while(p!=TT) { while(p->ltag==Link) //找到二叉樹左子樹最左端的結點,即中序遍歷的第一個結點 { p=p->lchild; }//while visit(p->data); //訪問其左子樹為空的結點 while(p->rtag==Thread&&p->rchild!=TT) { p=p->rchild; visit(p->data); }// /*假設沒有進行while迴圈,則該結點無左孩子有右孩子,由於已被訪問,則下一步就是訪問其右結點 */ /*假設執行了while迴圈,此時p不滿足while條件,說明p有右孩子,以p為根節點,既然p被訪問,則中*/ /*序遍歷剩下遍歷其右子樹 */ p=p->rchild; }//while }//InOrderTraverse_Thr template<class T> void BiTrTree<T>::visit(T data) { cout<<data; }//visit void main() { BiTrNode<char> *TT,*Thrt; BiTrTree<char> BTT; BTT.InputBiTrNode(); BTT.Pre_CreateBiTrTree(TT); BTT.InOrderThreading(Thrt,TT); cout<<"\n"<<"中序遍歷線索二叉樹:"<<endl; BTT.InOrderTraverse_Thr(Thrt); }//mian