http://acm.hdu.edu.cn/showproblem.php?pid=1710
/*
二叉树的遍历:
先序遍历(preorder traversal):先遍历父节点,然后是左孩子,右孩子。
中序遍历(inorder traversal):先遍历左孩子,然后是父节点,最后遍历右孩子。
后序遍历(postorder traversal):先遍历左孩子和右孩子,然后遍历父节点。
*/
题目大意:给出一个二叉树的先序和中序遍历序列,求后序遍历序列;
思路:将一棵二叉树分为根节点,左子树,右子树三部分。先让根节点入栈,然后递归处理右子树和左子树(必须先右后左)。最后依次出栈即得到后序遍历序列。
PS:本题解法是在假设所有节点数字不同的条件下进行的,题目并没有给出这个条件,不过能过测试。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stack>
using namespace std;
const int N=1005;
int preorder[N],inorder[N];
stack<int>postorder;
//二叉树由先序序列和中序序列求后序序列
void getpost(int pstart,int pend,int istart,int iend)
{
int i,j;
postorder.push(preorder[pstart]);
for(i=0;i<=iend;i++){ //i表示根节点在中序的位置
if(inorder[i]==preorder[pstart]) break;
}
j=pstart+(i-istart)+1; //j表示先序中左右子树的分界点
if(j<=pend && i+1<=iend){ //求解右子树
getpost(j,pend,i+1,iend);
}
if(pstart+1<=j-1 && istart<=i-1){ //求解左子树
getpost(pstart+1,j-1,istart,i-1);
}
}
int main()
{
int i,n;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++) scanf("%d",&preorder[i]);
for(i=0;i<n;i++) scanf("%d",&inorder[i]);
getpost(0,n-1,0,n-1);
while(!postorder.empty()){
printf("%d",postorder.top());
postorder.pop();
if(!postorder.empty())
printf(" ");
}
printf("\n");
}
return 0;
}