1. 程式人生 > >二叉樹擴充套件之三叉樹C++類模板的實現

二叉樹擴充套件之三叉樹C++類模板的實現

簡介

二叉樹是遞迴定義的,這裡的三叉樹同樣也是。

三叉樹分為左子樹,中子樹,右子樹。

三叉樹的遍歷順序方式,我把它則分為四種:

(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;
}