pat甲级1119 Pre- and Post-order Traversals
note:是否有唯一二叉树,关键在于看非叶节点中是否存在只有一个子树的根节点,若有,则二叉树不唯一,因为无法确定该子树是左子树还是右子树。题目中说二叉树不唯一时,输出其中一种可能的中序序列即可,因此可以将唯一的子树看作左子树,也可以看作右子树,我的做法是看作左子树。
中序遍历方法:首先要确定根节点和子树结点。根节点是先序序列的队首数字也是后序序列的队尾数字。若根节点为非叶子节点,则左子树必然存在,且左子树根节点为先序序列中根节点的下一个数;若先序序列中除根节点外的其他节点均在左子树中,则无右子树,反之则有右子树。然后按照左-中-右的方法递归即可。
采用顺序存储(数组或向量),由于不管先序还是后序序列,任意一棵子树的序列均为连续序列,故确定一棵子树有两种方法:第一是取序列的首尾地址(我用下标代替),第二种是取首地址或尾地址,再取序列长度。经过比较,第二种方法较简单清晰。
好了,废话不多说,上代码:
#include <iostream>
#include <vector>
using namespace std;
vector<int> pre,in,post;
bool flag=true;
void inorder(int preRoot,int num,int postRoot)
{
int i=0;//统计右子树结点个数
if(num>1)//若有左子树,隐含i<num-1
{
while(post[postRoot-i-1]!=pre[preRoot+1]) ++i;//右子树结点个数
if(!i) flag=false;//无右子树,标记;
inorder(preRoot+1,num-1-i,postRoot-i-1);//左子树递归
}
in.push_back(pre[preRoot]);
if(i) inorder(preRoot+num-i,i,postRoot-1);//若有右子树,递归
}
int main()
{
int n;
cin>>n;
pre.resize(n),post.resize(n);
for(int i=0;i<n;++i) cin>>pre[i];
for(int i=0;i<n;++i) cin>>post[i];
inorder(0,n,n-1);
printf("%s\n",flag?"Yes":"No");
for(int i=0;i<n;++i)
printf("%d%c",in[i],i<n-1?' ':'\n');
return 0;
}
//如果我的工作能让您得到一些帮助,那就是我最大的荣幸。
//ps:如果您能点一下赞,我就更荣幸了,哈哈O(∩_∩)O