ALDS1_7_D:Reconstruction of a Tree

输入:给出一个二叉树的前序遍历和中序遍历

输出:输出一个二叉树的后序遍历

题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_7_D

思路:前序遍历从头开始遍历的时候,第一个元素是根元素,根据这个元素,找到它在中序遍历中的位置,可以确定的是,这个元素在中序遍历序列中的位置,前面的都是这个根的左子树,后面的都是这个元素的右子树;比如对于前序{1,2,3,4,5},中序{3,2,4,1,5},前序的第一个元素是1,然后在中序遍历中找到它,那么说明{3,2,4}都是1的左子树,{5}是1的右子树。

对于左子树{3,2,4}而言,这是后序遍历,前序遍历是{2,3,4},那么2就是根元素,3是左子树,4是右子树。依次递归即可。

代码如下:

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> pre,in,post;
int root,pos=0;

void rec(int left,int right){
	if(left>=right) return ;
	int root=pre[pos++];
	int m=distance(in.begin(), find(in.begin(), in.end(),root));
	rec(left,m);
	rec(m+1,right);
	post.push_back(root);
	return ;
}

void solve(int n){
	rec(0,n);
	for(int i=0;i<n;i++) {
		if(i) cout<<" "<<post[i];
		else cout<<post[i];
	}
	cout<<endl;
	return ;
}

int main (){
	int n;
	cin>>n;
	int a;
	for(int i=0;i<n;i++){
		cin>>a;
		pre.push_back(a);
	}
	for(int i=0;i<n;i++){
		cin>>a;
		in.push_back(a);
	}
	solve(n);
	return 0;
}

错点:

1.find返回值是找到的值的迭代器,不是值。

 

同理也可以写出,已知中序和后序遍历求前序遍历的方法,代码如下:

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> pre,in,post;
int root,pos;

void rec(int left,int right){
	if(left>=right) return ;
	int root=post[pos--];
	int m=distance(in.begin(), find(in.begin(), in.end(),root));
	rec(m+1,right);
	rec(left,m);
	pre.push_back(root);
	return ;
}

void solve(int n){
	pos=post.size()-1;
	rec(0,n);
	for(int i=n-1;i>=0;i--) {
		if(i!=n-1) cout<<" "<<pre[i];
		else cout<<pre[i];
	}
	cout<<endl;
	return ;
}

int main (){
	int n;
	cin>>n;
	int a;
	for(int i=0;i<n;i++){
		cin>>a;
		in.push_back(a);
	}
	for(int i=0;i<n;i++){
		cin>>a;
		post.push_back(a);
	}
	solve(n);
	return 0;
}

但是在已知前序和后序遍历的情况下,无法还原出中序遍历的树,看了一些博客,原因大概是只有前后序的情况下,有信息的重复,也有信息的丢失,只能反映出父子节点的关系,不能反映出左右的关系。

已知先序和后序,不能唯一确定二叉树;

已知先序或后序,而又知中序,则能唯一确定二叉树;

先序、中序相同时,二叉树没有左子树;

后序、中序相同时,二叉树没有右子树;

后序、先序相同时,只有一个根节点;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值