1. 程式人生 > >二叉樹——前、中、後序遍歷遞迴以及非遞迴寫法

二叉樹——前、中、後序遍歷遞迴以及非遞迴寫法

#include <iostream>
#include <stack>
#include <queue>
using namespace std;

typedef struct Node{
	
	int data;
	
	Node *lchild;
	Node *rchild;
	Node()
	{
		data = 0;
		lchild = NULL;
		rchild = NULL;
	}

}BiTree,*BTree;
 

//前序建立二叉樹
void CreatBiTree(BTree& T,char data)
{
	cout<<"父節點:"<<data<<endl;
	char c;
	cin>>c;
	if(c =='#')
	{
		T=NULL;
	}else
	{
		T = new BiTree;
		T->data = c;
		CreatBiTree(T->lchild,T->data);
		CreatBiTree(T->rchild,T->data);
	}
	return;
}
/* 樹形

#############
	   1

	2	  5

 3	 4	 6	 7

#############
 前序: 1 2 3 4 5 6 7
 中序: 3 2 4 1 6 5 7
 後序: 3 4 2 6 7 5 1

*/


//建立二叉樹
void CreatTree(BTree& T)
{
	T = new BiTree;
	T->data = 1;
	//左子樹
	BTree T1 = new BiTree;
	T1->data = 2 ;
	T->lchild = T1; 
	
	BTree T11 = new BiTree;	
	T11->data = 3;
	T1->lchild = T11; 
	
	BTree T12 = new BiTree;
	T12->data = 4;
	T1->rchild = T12; 
	
	//右子樹
	BTree T2 = new BiTree;
	T2->data = 5 ;
	T->rchild = T2; 
	
	BTree T21 = new BiTree;	
	T21->data = 6;
	T2->lchild = T21; 

	BTree T22 = new BiTree;	
	T22->data = 7;
	T2->rchild = T22; 
	

	return;
}
 
//前序遞迴遍歷

void PreOrderBiTree(BiTree* T)
{	
  if(T)
  {
	  cout<<T->data <<" ";;
	  PreOrderBiTree(T->lchild);
	  PreOrderBiTree(T->rchild);
  }
}

//非遞迴前序《1》
/*****************
 先將右子樹放入棧底,依次放入左子樹元素
 按照左節點在上右節點在下原則	
 遇到葉節點 即開始彈出棧內元素	
******************/
void PreOredrTree1(BiTree *T)
{
  BiTree* p = T;
  stack<BiTree*> S;	//棧空間
  S.push(p);
  while(!S.empty())
  {
	  p = S.top();
	  S.pop();
	  cout<<p->data<<" ";
	  if(p->rchild)	   //右子樹節點入棧底
		  S.push(p->rchild);
	  if(p->lchild)	   //左子樹節點入棧
		  S.push(p->lchild);
  }
  return ;
}
//非遞迴前序《2》王道寫法
/*****************
 將所有的左子樹的左子節點入棧	同時 輸出值
 棧頂的左子節點出棧,訪問其右節點,
 若有 輸出其值 入棧 同時繼續將該節點的左子樹左節點入棧
 若無,繼續彈出下一個棧元素,訪問其右節點 	
******************/
void PreOredrTree(BiTree *T)
{
  BiTree* p = T;
  stack<BiTree*> S;	//棧空間

  while(!S.empty()||p!=NULL)
  {
	  if(p)
	  {
		  cout<< p->data <<" ";
		  S.push(p);
		  p = p->lchild;
	  }
	  else{
		  p = S.top();
		  S.pop();
		  p = p->rchild;
	  }
	 
  }
  return ;
}
//層序遍歷
void LeveOredrTree(BiTree *T)
{
  BiTree* p = T;
  queue<BiTree*> S;
  S.push(p);
  while(!S.empty())
  {
	  p = S.front();
	  S.pop();
	  cout<<p->data<<endl;
	  if(p->lchild)
		  S.push(p->lchild);
	  if(p->rchild)
		  S.push(p->rchild);

  }
  return ;

}
//中序遞迴遍歷
void InOrderBiTree(BiTree* T)
{	
  if(T)
  {
	  InOrderBiTree(T->lchild);
	   cout<<T->data <<" ";
	  InOrderBiTree(T->rchild);
  }
}

//非遞迴中序《1》王道寫法	   左根右 
/*****************
 將所有的左子樹的左子節點入棧	
 棧頂的左子節點出棧 <<<<輸出其值>>>> 訪問其右節點,	//區別在於此!!
 若有 入棧 同時繼續將該節點的左子樹左節點入棧
 若無,繼續彈出下一個棧元素,再訪問其右節點 	
******************/
void InOrderTree(BiTree *T)
{
  BiTree* p = T;
  stack<BiTree*> S;	//棧空間

  while(!S.empty()||p!=NULL)
  {
	  if(p)
	  {
		  S.push(p);
		  p = p->lchild;
	  }
	  else{
		  p = S.top();
		  cout<< p->data <<" ";
		  S.pop();
		  p = p->rchild;
	  }
	 
  }
  return ;
}

//後序遞迴遍歷

 void PostOrderBiTree(BiTree* T)
{	
  if(T)
  {
	  PostOrderBiTree(T->lchild); 
	  PostOrderBiTree(T->rchild);
	  cout<<T->data <<" ";
  }
}

 //非遞迴後序《1》王道寫法	   左右根 
/*****************
 將所有的左子樹的左子節點入棧	
 棧頂最後一個左節點出棧,判斷其是否還有右根,
 若有,右根入棧 同時繼續將該右根的左子樹的所有左節點入棧
 若無,彈出該節點,輸出其值,同時記錄該節點?	
 
 用做此的父節點出棧時的對比,避免此 節點 重複入棧

******************/
void PostOrderTree(BiTree *T)
{
  BiTree* p = T;
  BiTree* k = NULL;//用於標記改節點是否已經訪問其右節點

  stack<BiTree*> S;	//棧空間

  while(!S.empty()||p!=NULL)
  {
	  if(p)
	  {
		  S.push(p);
		  p = p->lchild;
	  }
	  else{
		  p = S.top();	//先不出棧
		  if(p->rchild != NULL && k != p->rchild)//判斷p出棧時p的右子樹有無入棧(沒有:p不能出棧,繼續將右子樹入棧。有:p可以出棧 )
		  {
			 p = p->rchild;	//繼續將右節點的所有子樹左節點入棧
		  }
		  else{
			  cout<< p->data<<" ";//輸出節點值
			  S.pop();	 //節點出棧
			  k = p; 
			  p = NULL;
		  }
	  }
	 
  }
  return ;
}

int main()
{
	BiTree* T;
	CreatTree(T);	
	cout<<"建立二叉樹完成!"<<endl;

	cout<<"前序遍歷二叉樹: 1 2 3 4 5 6 7 "<<endl;
	PreOrderBiTree(T);
	cout<<endl<<"非遞迴前序遍歷二叉樹!"<<endl;
	PreOredrTree(T);
	cout<<endl<<"中序遍歷二叉樹: 3 2 4 1 6 5 7  "<<endl;
	InOrderBiTree(T);
	cout<<endl<<"非遞迴中序遍歷二叉樹!"<<endl;
	InOrderTree(T);

	cout<<endl<<"後序遍歷二叉樹: 3 4 2 6 7 5 1"<<endl;
	PostOrderBiTree(T);
	cout<<endl<<"非遞迴後序遍歷二叉樹!"<<endl;
	PostOrderTree(T);
	cout<<endl;

	system("pause")	;
	return 0;
}