二叉树的遍历及例题

二叉树的遍历及例题

前序遍历就是根在前,中序就是根在中,

前序遍历

根 --> 左 --> 右

中序遍历

左 --> 根 --> 右

后序遍历

左 --> 右 --> 根

如图是一颗二叉树

前序(根左右),中序(左根右),后序(左右根)

它的前序遍历结果为: A B D F G H I E C 代表的含义为A( B ( D ( F ,G( H ,I ) ) ,E ) , C )

所以第一个点一定是根节点

它的中序遍历结果为: F D H G I B E A C

它代表的含义,A(已知它不是叶子节点)在中间说明A的左边是左儿子,A的右边是他的右儿子

它的后序遍历结果为:F H I G D E B C A

解题:

如果有前序和中序或者中序和后序可以得到二叉树,从而得到后序。

如果有前序和后序无法的得到二叉树。

1.已知前序、中序遍历求后序遍历

例:

​ 前序遍历:A B G D E C F H

​ 中序遍历:G B E D A F C H

构建二叉树的步骤:

1.根据前序遍历特点,得到根节点A

2.观察中序遍历结果: 根节点左边节点为G B E D,根节点的右边节点为 F C H。同时,两段也是左右子树的中序遍历的结果。

​ B G D E也是左子树前序遍历的结果。 C F H也是右子树前序遍历的结果。

3.重复 1 2的步骤,直到找到叶子结点就可以得到最后的二叉树。

例题:

https://vjudge.net/contest/407936#problem/K

题意:给出中序遍历和前序遍历,让你找到后序遍历的结果。

#include <iostream>
using namespace std;
const int maxn = 105;  
int pre[maxn],in[maxn],pos[maxn];

int infind(int root,int l,int r){//在中序遍历中找到当前根节点的位置 
	for(int i=l;i<r;i++){
		if(in[i]==root){
			return i;
		}
	}	
}
int cnt;

void posorder(int prel,int prer,int inl,int inr){
	if(prel==prer) return ;
	int root=infind(pre[prel],inl,inr);//找当前的根的位置 
	int len=root-inl;
	posorder(prel+1,prel+1+len,inl,inl+len);//prel的位置是root的位置,删去
	posorder(prel+1+len,prer,inl+1+len,inr);//inl+len+1的位置是root的位置,删去
    //进行完左边和右边的遍历之后,进行赋值。 左右根
	pos[cnt++]=in[root];
	return;
}

int main(){
	int n;
	while(~scanf("%d",&n)){
		cnt=0;
		for(int i=0;i<n;i++) cin>>in[i];
		for(int i=0;i<n;i++) cin>>pre[i];
		posorder(0,n,0,n);
		for(int i=0;i<n;i++) cout<<pos[i]<<' ';
		cout<<endl;
	}
	return 0;
} 
//关键代码:

void posorder(int prel,int prer,int inl,int inr){
	if(prel==prer) return ;
	int root=infind(pre[prel],inl,inr);//找当前的根的位置 
	int len=root-inl;
	posorder(prel+1,prel+1+len,inl,inl+len);
	posorder(prel+1+len,prer,inl+1+len,inr);
	pos[cnt++]=in[root];//相当于输出操作
	return;
}

//得到前序遍历的值
pos[cnt++]=in[root];//相当于输出操作
posorder(prel+1,prel+1+len,inl,inl+len);
posorder(prel+1+len,prer,inl+1+len,inr);

//得到中序遍历的值
posorder(prel+1,prel+1+len,inl,inl+len);
pos[cnt++]=in[root];//相当于输出操作
posorder(prel+1+len,prer,inl+1+len,inr);

//得到后序遍历的值
posorder(prel+1,prel+1+len,inl,inl+len);
posorder(prel+1+len,prer,inl+1+len,inr);
pos[cnt++]=in[root];//相当于输出操作

例题:

玩转二叉树

https://pintia.cn/problem-sets/994805046380707840/problems/994805065406070784

题意:给你中序遍历和前序遍历的结果,让你找到二叉树的镜像,然后按层遍历输出

#include <iostream>
using namespace std;
int pre[55],in[55],pos[55];
int ans[55][55];//储存按层遍历的结果
//第一个存的哪一层,第二个存的是具体的数,
//ans[t][0]存储的是该层的数字个数。
int find(int t,int l,int r){
	for(int i=l;i<r;i++){
		if(in[i]==t){
			return i;
		}
	}
}

void ceng(int prel,int prer,int inl,int inr,int t){
	if(prel==prer) return ;
	ans[t][++ans[t][0]]=pre[prel];//存入答案。
	int x=find(pre[prel],inl,inr);
	int len=x-inl;
	ceng(prel+len+1,prer,inl+len+1,inr,t+1);//先遍历右边,再遍历左边
	ceng(prel+1,prel+len+1,inl,inl+len,t+1);
	return;
}

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>in[i];
	for(int i=0;i<n;i++) cin>>pre[i];
	ceng(0,n,0,n,0);
	int x=0;
		int len=0;
	while(ans[x][0]!=0){
	
		for(int i=1;i<=ans[x][0];i++){
			if(len==0){
				printf("%d",ans[x][i]);
			}else{
				printf(" %d",ans[x][i]);
			}
			len++;
			
		}
		x++;
	}
	return 0;
}

2.已知后序、中序遍历求前序遍历

后序遍历是:左右根,所以根在最后,跟前序遍历相似,把 prel 和 prer 的值改变一下即可。

3.已知前序、后序遍历求中序遍历

无法求得!!!

posted @ 2020-11-16 21:36  ACHanHan  阅读(7547)  评论(0编辑  收藏  举报