An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: “Push X” where X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.
Output Specification:
For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop
Sample Output:
3 4 2 6 5 1
分析
pop相当于说中序遍历,而push相当于前序遍历,我们用两个数组来记录中序遍历与前序遍历的答案,也就是pre[]和in[] 递归函数是两个数组的最小索引和最大索引
然后pre的最小索引的元素a一定是结点,然后a在in左边的全是左子树,右边的全是右子树,再这样递归下去,算法也就变成了不停找根结点的,但是这里需要注意的是递归的时候,前序最好都写成中序的相对位置
int build(int L1 ,int R1,int L2,int R2)
{
if(L2 > R2||L1>R1)
return null;
int root = pre[L1];
T[root].data = pre[L1];
int index = v[pre[L1]]; //中序遍历的位置
//cout<<T[root].data<<endl;
T[root].L = build(L1+1,L1+index-L2,L2,index-1);
T[root].R = build(L1+index+1-L2,R1,index+1,R2);
return root;
}
完整代码
#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<string.h>
const int MAXN=100000;
const int null=-1;
using namespace std;
stack<int> s;
int pre[MAXN],in[MAXN],v[MAXN],pos[MAXN];
int precount=0,incount=0;
int n;
typedef struct TR{
int data;
int L;
int R;
}TR;
TR T[MAXN];
bool f=1;
int build(int L1 ,int R1,int L2,int R2)
{
if(L2 > R2||L1>R1)
return null;
int root = pre[L1];
T[root].data = pre[L1];
int index = v[pre[L1]]; //中序遍历的位置
//cout<<T[root].data<<endl;
T[root].L = build(L1+1,L1+index-L2,L2,index-1);
T[root].R = build(L1+index+1-L2,R1,index+1,R2);
return root;
}
void dfs(int root)
{
if(T[root].L!=null)
dfs(T[root].L);
if(T[root].R!=null)
dfs(T[root].R);
if(f)
{
cout<<T[root].data;
f=0;
}
else
cout<<" "<<T[root].data;
}
int main()
{
string cmd;
cin>>n;
for (int i = 0; i < 2*n; ++i)
{
cin>>cmd;
if(cmd[1]=='u')
{
int a;
cin>>a;
s.push(a);
pre[precount++]=a; //储存先序遍历
}
if(cmd[1]=='o')
{
int temp = s.top();
s.pop();
v[temp] = incount; //储存中序遍历的索引
in[incount++]=temp; //储存中序遍历
}
}
//接下来是建树过程
build(0,n-1,0,n-1);
dfs(pre[0]);
return 0;
}