这个题就是给你二叉树的先序和中序遍历,让你输出后序遍历的结果。
按照顺序出现的节点值就是节点的先序,但是中序是根据栈操作得到的。
那么直接根据先序和中序建树即可。
但是这里有一个问题,就是输入的节点值可能存在相等的情况,这会使得遍历出现各种段错误和答案错误。
所以我们可以按照每个节点出现的顺序的编号进行建树。
#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; }