PAT_A1086
PAT甲级1086.
目录
A1086
题目
样例
输入:
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop
输出:
3 4 2 6 5 1
思路和坑点
通树的先序和中序的非递归算法可以直到,栈的push序列是其先序序列,pop序列是其中序序列。因此通过栈的模拟分别获得先序和中序序列,然后由此建树,可以直接在递归函数中加一个后序的下标位置作为参数,直接获得后序遍历的结果。
AC代码
#include<bits/stdc++.h>
using namespace std;
vector<int> pre,in,post; //用于存放先序、中序、后序的序列
//树的后序序列创建函数
//pl,pr,il,ir,pos分别表示当前的先序序列的左右端下标,中序序列的左右下标,以及在后序中根的位置
void creat(int pl,int pr,int il,int ir,int pos){
if(pl>pr) return; //如果当前递归的子树中没有结点,直接返回
post[pos]=pre[pl]; //先序的第一个便是根,放在后序序列的相应位置上
int k,leftnum,rightnum; //k表示根在中序中的位置下标,leftnum和rightnum分别表示左右子树元素个数
for(k=il;k<=ir;k++){ //确定k
if(in[k]==pre[pl])
break;
}
leftnum=k-il; rightnum=ir-k; //确定左右子树的元素个数
creat(pl+1,pl+leftnum,il,k-1,pos-rightnum-1); //递归左子树
creat(pl+leftnum+1,pr,k+1,ir,pos-1); //递归右子树
}
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
post.resize(n);
stack<int> s;
for(int i=0;i<n*2;i++){ //有n*2此操作
string tag;
cin>>tag; //操作的类型
if(tag=="Push"){
int num; scanf("%d",&num); //如果是push,读入相应的数字分别压入栈和前序序列中
pre.push_back(num);
s.push(num);
}
else{
in.push_back(s.top()); //如果是pop,出栈顺序为中序序列,并从栈中出栈
s.pop();
}
}
creat(0,n-1,0,n-1,n-1); //建树并输出
for(int i=0;i<n;i++){
if(i) putchar(' ');
printf("%d",post[i]);
}
return 0;
}