二叉樹擴充套件之三叉樹C++類模板的實現
阿新 • • 發佈:2019-02-17
簡介
二叉樹是遞迴定義的,這裡的三叉樹同樣也是。
三叉樹分為左子樹,中子樹,右子樹。
三叉樹的遍歷順序方式,我把它則分為四種:
(1)先序:根->左->中->右
(1)中1序:左->根->中->右
(1)中2序:左->中>根->右
(1)後序:左->中->右->根
例如以下一棵三叉樹:
將其以如下方式進行儲存在test.txt檔案中(便於程式先序讀取建立一顆樹,空用#表示)
ABC###D####E#F####G#H###IJ###K###M###
對於上面這棵樹,從之後的程式設計實現對其遍歷有如下結果。
程式設計實現
1.首先建立一個TTNode.h
#ifndef TTNODE_H
#define TTNODE_H
template <typename T>
struct TTNode{
T data;
TTNode<T> *lchild,*mchild,*rchild;
};
#endif
2.建立TTree.h
#ifndef TTREE_H #define TTREE_H enum Tags{ Left,Mid,Right }; enum style{ Pre,In01,In02,Post }; template <typename T> struct StackElem{ TTNode<T> *p; Tags flag; }; template <typename T> class TTree{ protected: TTNode<T> *root; private: void DestroyTTree(TTNode<T>* &t){ if(t!=NULL){ DestroyTTree(t->lchild); DestroyTTree(t->mchild); DestroyTTree(t->rchild); delete t; t=NULL; } } public: TTree(){ root=NULL; } ~TTree(){ DestroyTTree(root); } void CreateTTreeFromFile(ifstream &f){ T e; InputFromFile(f,e); if(e==Nil) return ; root =new TTNode<T>; assert(root!=NULL); root->data=e; TTree<T> left,mid,right; left.CreateTTreeFromFile(f); mid.CreateTTreeFromFile(f); right.CreateTTreeFromFile(f); root->lchild=left.root; left.root=NULL; root->mchild=mid.root; mid.root=NULL; root->rchild=right.root; right.root=NULL; } bool TTreeEmpty()const{ return root==NULL; } int TTreeDepth(TTNode<T>* t){ int i,j,k,bri; if(t==NULL) return 0; else{ i=TTreeDepth(t->rchild); k=TTreeDepth(t->mchild); j=TTreeDepth(t->lchild); bri=i>j?i:j; return bri>k?bri+1:k+1; } } TTNode<T>* Root(){ return root; } T Value(TTNode<T>* p)const{ return p->data; } void Assign(TTNode<T>* p,T value){ p->data=value; } void PreOrderTraverse(void(*visit)(TTNode<T>*))const{ stack<TTNode<T>*> s; TTNode<T> *t=root; s.push(NULL); while(t!=NULL){ visit(t); if(t->rchild!=NULL) s.push(t->rchild); if(t->mchild!=NULL) s.push(t->mchild); if(t->lchild!=NULL) t=t->lchild; else{ t=s.top(); s.pop(); } } } void In01OrderTraverse(void(*visit)(TTNode<T>*))const{ StackElem<T> se; stack<StackElem<T> > s; TTNode<T> *t=root; if(t==NULL) return ; while(!s.empty()||t!=NULL){ while(t!=NULL){ se.p=t; se.flag=Left; s.push(se); t=t->lchild; } se=s.top(); s.pop(); t=se.p; if(se.flag==Left){ visit(t); se.flag=Mid; s.push(se); t=t->mchild; } else{ if(se.flag==Mid){ se.flag=Right; s.push(se); t=t->rchild; } else{ t=NULL; } } } } void In02OrderTraverse(void(*visit)(TTNode<T>*))const{ StackElem<T> se; stack<StackElem<T> > s; TTNode<T> *t=root; if(t==NULL) return ; while(!s.empty()||t!=NULL){ while(t!=NULL){ se.p=t; se.flag=Left; s.push(se); t=t->lchild; } se=s.top(); s.pop(); t=se.p; if(se.flag==Left){ se.flag=Mid; s.push(se); t=t->mchild; } else{ if(se.flag==Mid){ visit(t); se.flag=Right; s.push(se); t=t->rchild; } else{ t=NULL; } } } } void PostOrderTraverse(void(*visit)(TTNode<T>*))const{ StackElem<T> se; stack<StackElem<T> > s; TTNode<T> *t=root; if(t==NULL) return ; while(!s.empty()||t!=NULL){ while(t!=NULL){ se.p=t; se.flag=Left; s.push(se); t=t->lchild; } se=s.top(); s.pop(); t=se.p; if(se.flag==Left){ se.flag=Mid; s.push(se); t=t->mchild; } else{ if(se.flag==Mid){ se.flag=Right; s.push(se); t=t->rchild; } else{ visit(t); t=NULL; } } } } void LevelOrderTraverse(void(*visit)(TTNode<T>*))const{ queue<TTNode<T>*> q; TTNode<T> *a,*t=root; if(t!=NULL){ q.push(t); while(!q.empty()){ a=q.front(); q.pop(); visit(a); if(a->lchild!=NULL) q.push(a->lchild); if(a->mchild!=NULL) q.push(a->mchild); if(a->rchild!=NULL) q.push(a->rchild); } } cout<<endl; } void OrderTraverse (TTNode<T>* t,style mode,void(*visit)(TTNode<T>*))const{ if(t!=NULL){ if(mode==Pre) visit(t); OrderTraverse(t->lchild,mode,visit); if(mode==In01) visit(t); OrderTraverse(t->mchild,mode,visit); if(mode==In02) visit(t); OrderTraverse(t->rchild,mode,visit); if(mode==Post) visit(t); } } }; #endif
3.此外習慣將標頭檔案組合在一起也弄個頭檔案C.h(多可少不行)
#ifndef C_H #define C_H #include <iostream> #include <fstream> #include <iomanip> #include <cmath> #include <string> #include <vector> #include <list> #include <stack> #include <queue> #include <algorithm> #include <assert.h> using namespace std; #endif
4.最後是測試程式碼
#include "C.h"
#include "TTNode.h"
typedef char T;
void Visit(TTNode<T> *c){
cout<<c->data<<" ";
}
void InputFromFile(ifstream &f,T &c){
f>>c;
}
void Input(T &c){
cin>>c;
}
T Nil='#';
#include "TTree.h"
int main()
{
TTree<T> t,c;
TTNode<T> *p, *q;
T e;
ifstream fin("test.txt");
t.CreateTTreeFromFile(fin);
fin.close();
cout<<"由檔案test.txt建立三叉樹t後,樹t空否?"<<boolalpha<<t.TTreeEmpty();
cout<<"。樹t的深度="<<t.TTreeDepth(t.Root())<<endl;
cout<<endl<<"層序遍歷刪除後的三叉樹t:";
t.LevelOrderTraverse(Visit);
p=t.Root();
cout<<endl<<"t的根結點="<<t.Value(p)<<"。給根結點賦新值,請輸入新值:";
Input(e);
t.Assign(p, e);
cout<<endl<<"層序遍歷刪除後的三叉樹t:";
t.LevelOrderTraverse(Visit);
cout<<endl<<"先序遍歷刪除後的三叉樹t:";
t.PreOrderTraverse(Visit);
cout<<endl<<"先序遞迴遍歷刪除後的三叉樹t:";
t.OrderTraverse(t.Root(), Pre, Visit);
cout<<endl;
cout<<endl<<"中1序遍歷刪除後的三叉樹t:";
t.In01OrderTraverse(Visit);
cout<<endl<<"中1序遞迴遍歷刪除後的三叉樹t:";
t.OrderTraverse(t.Root(), In01, Visit);
cout<<endl;
cout<<endl<<"中2序遍歷刪除後的三叉樹t:";
t.In02OrderTraverse(Visit);
cout<<endl<<"中2序遞迴遍歷刪除後的三叉樹t:";
t.OrderTraverse(t.Root(), In02, Visit);
cout<<endl;
cout<<endl<<"後序遍歷刪除後的三叉樹t:";
t.PostOrderTraverse(Visit);
cout<<endl<<"後序遞迴遍歷刪除後的三叉樹t:";
t.OrderTraverse(t.Root(), Post, Visit);
return 0;
}