PAT甲级 1119 Pre- and Post-order Traversals (30分) C++

1119 Pre- and Post-order Traversals (30分)

题目大意:给定前序和后序,要求输出中序,并判断是否唯一。

首先要知道:

先序:根结点-> 左孩子 -> 右孩子

后序:从后往前: 根结点 -> 右孩子 -> 左孩子

首先找到根结点,(前序第一个和后序最后一个值为根)后序指针往前移动一位(先将其默认认为是根的右孩子结点),找到前序中对应的值:从前序的根出发直到找到该值(右孩子)中间经过的所有元素为根的左孩子,计算出左孩子的个数。 以此为依据便可以分别在前序和后序中划分左右孩子。

如果在寻找的过程中,左孩子为0,表明原来指定的右孩子可以为左孩子也可以为右孩子(无法确定)。

例如:
在这里插入图片描述

像这样的一棵树,其前序为:0123456,后序为2315640

  1. 第一步:此时0为根结点,后序往前一位(4)即为根结点的右孩子(先假设其为右孩子,也可能为左孩子),在前序中找到该结点,经过了三个结点(count),这三个结点在4之前出现,表明其在根的左边,此时可以确定4是右孩子。
    如果123不存在,则无法确定4是左孩子还是右孩子(因此可以用count来判断是否唯一

  2. 第二步:递归地将其分为左右孩子,然后重复第一步(start1+1/end2-1为根结点)
    左孩子:前序为:start1 +1 ~ start1+count+1;后序为:start2 ~ start2+count
    右孩子:前序为:start1+count+1 ~ end1;后序为:start2+count ~ end2-1

#include<iostream>                  //输入输出流头文件
#include<vector>                    //变长数组容器
using namespace std;               //标准命名空间
int n,isUnique=1;
vector<int> preorder,postorder,in;
void inorder(int s1,int e1,int s2,int e2);
int main(){                         //主函数
#ifdef ONLINE_JUDGE                 //如果有oj系统(在线判定),则忽略文件读入,否则使用文件作为标准输入
#else    
   freopen("1.txt", "r", stdin);   //从1.txt输入数据
#endif 
   cin>>n;
   preorder.resize(n);
   postorder.resize(n);
   for(int i=0;i<n;i++) cin>>preorder[i];
   for(int i=0;i<n;i++) cin>>postorder[i];
   inorder(0,n-1,0,n-1);
   if(isUnique) cout<<"Yes"<<endl;
   else cout<<"No"<<endl;
   for(int i=0;i<n;i++){
	   cout<<in[i];
	   if(i<n-1)cout<<' ';
	   else cout<<endl;
   }
    return 0;                       //返回0,如果不返回0,PAT会报错
}
void inorder(int s1,int e1,int s2,int e2){
    if(s1>e1)return ;//越界
	if(s1==e1) {//此时为叶子结点
		in.push_back(preorder[s1]);
		return ;
	}
	int count=0;
	while(s1+count<e1){
		if(preorder[s1+count]==postorder[e2-1]) break;
		count++;
	}
	if(count<2)isUnique=0;
	else inorder(s1+1,s1+count-1,s2,s2+count-2);//左孩子
	in.push_back(postorder[e2]);
	inorder(s1+count,e1,s2+count-1,e2-1);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值