二叉树——前、中、后序遍历递归以及非递归写法

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


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值