03-树3 Tree Traversals Again
原题链接
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.
Figure 1
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
结尾无空行
思路
不管Push
和Pop
->先序遍历
基于push和pop,进行栈模拟->中序遍历
先序遍历+中序遍历->求后序遍历
核心算法
(根据陈越PTA讲解视频临摹的代码)
//PreL为该伦的先序遍历的开始下标
//inL为该伦的中序遍历的开始下标
//PostL为该伦的后序遍历的开始下标
//len为该伦递归子串的长度
void solve(int PreL,int inL,int PostL,int len){
if(n==0){
return;//最特殊的情况:末尾时,右子串为空n==0
}
if(n==1){
post[PostL]=pre[PreL];//只有一个元素的情况下post,int,pre都是相同元素
}
post[PostL+len-1]=pre[PreL];//将先序遍历中的“根节点”存到后序遍历的最后
int L,R;//左右子串的长度
for(int i=0;in[i]!=pre[PreL];i++);//寻找该伦根节点的位置
L=i;//左子串的个数=i
R=len-i-1;//右子串长度=子串长度- 左子串长度-根节点(1)
solve(PreL+1,inL,PostL,L);
//递归左子串->左子串先序遍历从PreL+1开始,inL,PostL遍历顺序不变
solve(PreL+L+1,inL+L+1,PostL+L,R);
//递归右子串 ->右子串先序遍历从(跳过左子串和根节点长度开始)PreL+L+1
//中序遍历也是从(跳过左子串和根节点长度开始)inL+L+1
//后序遍历从(跳过左子串长度开始)PostL+L
}
//main函数中的调用
solve(0,0,0,len);
Code
#include<iostream>
#include<stack>
#include<vector>
#define MaxSize 30
using namespace std;
vector<int> postorder;
void postorderPrint(int preorder[],int inorder[],int root,int start,int end){
if(start>end)
return;
int i=start;
while(i<end&&inorder[i]!=preorder[root]){
i++;
}
postorderPrint(preorder,inorder,root+1,start,i-1);//左子树
postorderPrint(preorder,inorder,root+(i-start+1),i+1,end);//右子树
postorder.push_back(preorder[root]);
}
int main(){
int N,pi=0,ii=0;
cin>>N;
stack<int> st;
int preorder[N],inorder[N];//用来存先序和中序遍历的数组
int total=2*N;
//存先序和中序遍历进数组
while(total--){
string op;
cin>>op;
if(op=="Push"){
int num;
cin>>num;
preorder[pi++]=num;
st.push(num);
}else{//POP
if(!st.empty()){
inorder[ii++]=st.top();
st.pop();
}
}
}
postorderPrint(preorder,inorder,0,0,N-1);
for(int i=0;i<N;i++){
if(i!=0){
printf(" ");
}
cout<<postorder[i];
}
return 0;
}
先序遍历+中序遍历->后序遍历
#include<iostream>
using namespace std;
int pre[]={1, 2, 3, 4, 5, 6};//前序序列
int in[]={3, 2, 4, 1, 6, 5};//中序序列
void post(int root,int start,int ends){//后序打印
if(start>ends){
return;
}
int i=start;
while(i<ends&&in[i]!=pre[root]){//找到中序序列中根结点的位置
i++;
}
post(root+1,start,i-1);//遍历左子树
post(root+(i-start+1),i+1,ends);//遍历右子树
cout<<pre[root]<<' ';
}
int main(){
post(0,0,5);
return 0;
}