这个题就是给你二叉树的先序和中序遍历,让你输出后序遍历的结果。
按照顺序出现的节点值就是节点的先序,但是中序是根据栈操作得到的。
那么直接根据先序和中序建树即可。
但是这里有一个问题,就是输入的节点值可能存在相等的情况,这会使得遍历出现各种段错误和答案错误。
所以我们可以按照每个节点出现的顺序的编号进行建树。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
const int maxn=35;
vector<int> ans,pre,in,value;
int n,num,key;
string s;
stack<int> st;
void build(int l1,int r1,int l2,int r2)
{
if(l2>r2) return ;
int p=l2;
int root=pre[l1];//注意这里是根节点的顺序值
while(in[p]!=root) p++;
int cnt=p-l2;//左子树节点个数
build(l1+1,l1+cnt,l2,p-1);
build(l1+cnt+1,r1,p+1,r2);
ans.push_back(root);//这里建树的过程就能得到后序遍历的结果,不需要单独遍历
}
int main()
{
scanf("%d",&n);
key=0;
for(int i=1; i<=2*n; i++)
{
cin >> s;
if(s=="Push")
{
cin >> num;
value.push_back(num);//单独存节点值
pre.push_back(key);//先序中序都是节点的顺序值
st.push(key++);
}
else
{
in.push_back(st.top());
st.pop();
}
}
build(0,n-1,0,n-1);
if(ans.size()>0) printf("%d",value[ans[0]]);
for(int i=1;i<ans.size();i++)
printf(" %d",value[ans[i]]);
return 0;
}
这里再记录一个不一样的建树代码
#include <cstdio>
#include <vector>
#include <stack>
#include <cstring>
using namespace std;
vector<int> pre, in, post,value;
void postorder(int root, int start, int end) {
if (start > end) return;
int i = start;
while (i < end && in[i] != pre[root]) i++;
postorder(root + 1, start, i - 1);
postorder(root + 1 + i - start, i + 1, end);
post.push_back(pre[root]);
}
int main() {
int n;
scanf("%d", &n);
char str[5];
stack<int> s;
int key=0;
while (~scanf("%s", str)) {
if (strlen(str) == 4) {
int num;
scanf("%d", &num);
value.push_back(num);
pre.push_back(key);
s.push(key++);
} else {
in.push_back(s.top());
s.pop();
}
}
postorder(0, 0, n - 1);
printf("%d", value[post[0]]);
for (int i = 1; i < n; i++)
printf(" %d",value[post[i]]);
return 0;
}