解题报告-PAT- Tree Traversals Again
Tree Traversals Again有两种解题思路:
1、在Push和Pop的过程中记录后序序列。
2、构造先序序列和中序序列,然后build后序序列。
PAT原题链接:https://www.patest.cn/contests/pat-a-practise/1086
下面给出两种算法:
算法1:
算法2:
1、在Push和Pop的过程中记录后序序列。
2、构造先序序列和中序序列,然后build后序序列。
PAT原题链接:https://www.patest.cn/contests/pat-a-practise/1086
下面给出两种算法:
算法1:
# include <stdio.h>
# include <string.h>
# include <iostream>
# define MAX 60
typedef struct stack{
int top;
int data[MAX];
int flag[MAX]; //标记变量 0.表示在访问左子树,1.表示在访问右子树。只有在访问右子树弹出栈的时候才输出
}ST;
/**
算法思想:
一个入栈出栈序列,之所以能唯一确定一颗树,就是因为,入栈顺序是中序遍历,出栈顺序是先序遍历。
而先序中序可以唯一确定一颗树,那么这里我们就有两种思路:
1.先保存先序遍历序列和中序遍历序列,递归调用build(n,s1,s2,ans);求解后序遍历序列。
2.没必要保存,在Push和Pop的过程中暗含了一些顺序信息。
新建栈s。
当中序遍历Push时,说明在访问左子树,这时候我们把节点放入堆栈,并设置标签0,表示在访问左子树的过程中。
当中序遍历Pop时,说明是左子树访问完毕返回的情况,我们并不真的pop s的元素,而是把s的栈顶元素设置为1,表示现在这个节点
在中序遍历中已出栈,在访问右孩子的过程中。在设置栈顶元素为1之前要先pop掉所有栈顶为1的元素,这些元素已经是确定的
后序遍历序列。
输入为Push: 那么往s里面push,同时标记0
输入为Pop: 那么先从堆栈s里面pop出标记为1的节点,从栈顶开始,到标记为0结束,同时输出。再把栈顶元素设置为1,表示要访问
栈顶元素的右孩子。
**/
ST s; //定义栈
int main(){
char str[10];
int t, n, ans[MAX], j=0;
cin >> n;
s.top = 0; //代表栈中有0个元素
for(int i = 0; i < MAX; i++){
s.flag[i] = 0;
}
for(int i = 0;i < 2*n; i++){
cin >> str;
if(strcmp(str,"Push") == 0){ //直接push
cin >> t;
s.data[s.top] = t;
s.flag[s.top++] = 0;
}else{ //输入的是pop
//弹出栈顶标记为1的元素
while(s.top!=0){
if(s.flag[s.top-1] == 1)
ans[j++] = s.data[--s.top];
else
break;
}
s.flag[s.top-1] = 1; //栈顶元素设置为1表示继续访问栈顶的右孩子。
}
}
while(s.top!=0) //栈中还有元素未出栈,依次出栈
ans[j++] = s.data[--s.top];
for(int i=0;i<n;i++){
if(i) printf(" ");
printf("%d",ans[i]);
}
return 0;
}
算法2:
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <stack>
# define MAX 60
using namespace std;
stack<int> s;
void build(int n,char *s1,char* s2,char *s){
if(n<=0) //没有节点要转换
return;
int p=strchr(s2,s1[0]) - s2; //寻找s1[0]在s2中的下标
build(p,s1+1,s2,s);
build(n-p-1,s1+p+1,s2+p+1,s+p); //递归求右边n-p-1个节点
s[n-1]=s1[0];
}
int main(){
char str[5];
int s1[MAX],s2[MAX];
int j1=0,j2=0,t,n;
cin >> n;
for(int i=0;i<2*n;i++){
cin>>str;
if(strcmp(str,"Push") == 0){
cin>>t;
s.push(t);
s1[j1++] = t;
}else{
s2[j2++]=s.top();
s.pop();
}
}
char str1[MAX],str2[MAX],ans[MAX];
for(int i=0;i<n;i++){
str1[i] = s1[i]+'0';
str2[i] = s2[i]+'0';
}
build(n,str1,str2,ans);
ans[n]='\0';
for(int i=0;i<n;i++){
if(i) printf(" ");
printf("%c",ans[i]);
}
printf("\n");
return 0;
}
其中算法2在PAT的提交测试中,N=30,复杂组合,测试点5没有通过。留待后序研究,或者有知道原因的也可以联系我。