题目描述
现有一棵n个结点的二叉树(结点编号为从0
到n-1
),已知其先序序列和中序序列,求后序序列。
思考
例子
preOrder 0 2 1 4 5 3
inOrder 1 2 4 0 5 3
对于preOrder和inOrder序列分别设有两个指针preL,preR,inL,inR。
任意情况下,从根节点划分,在中序遍历中,用index记录inOrder中根节点的下标,则左子树的个数应该为flag = index - preL,则剩下的(除去根节点和左子树中的节点)都是右子树节点。所以对于inOrder中左子树范围为inL——index - 1,右子树范围为index + 1,inR;对于preOrder左子树的范围为preL + 1——preL + flag,右子树的范围为preL + flag + 1——preR;由此就推出了递归式。
0的左子树:
preOrder 2 1 4
inOrder 1 2 4
所以划分为
build(preL + 1,preL + flag,inL,index - 1);
同理再去划分右子树
build(preL + flag + 1,preR,index + 1,inR);
代码
#include <iostream>
#include <vector>
using namespace std;
const int N = 50;
struct node{
int l;
int r;
} nodes[N];
int n;
vector<int> pre,in,post;
void postOrder(int root)
{
if(root == -1) return;
postOrder(nodes[root].l);
postOrder(nodes[root].r);
post.push_back(root);
}
int build(int preL,int preR,int inL,int inR)
{
if(preL > preR) return -1;
int root = pre[preL];
int index;
//找到中序序列中的根节点位置
for(int i = inL;i <= inR;i++)
if(in[i] == root)
{
index = i;
break;
}
/**
preOrder 0 2 1 4 5 3
inOrder 1 2 4 0 5 3
root = 0;index = 3;flag = 3
0的左子树:
preOrder 2 1 4
inOrder 1 2 4
所以划分为
build(preL + 1,preL + flag,inL,index - 1);
同理再去划分右子树
**/
int flag = index - inL;
nodes[root].l = build(preL + 1,preL + flag,inL,index - 1);
nodes[root].r = build(preL + flag + 1,preR,index + 1,inR);
return root;
}
int main()
{
cin>>n;
int x;
for(int i = 0;i < n;i++)
{
cin>>x;
pre.push_back(x);
}
for(int i = 0;i < n;i++)
{
cin>>x;
in.push_back(x);
}
int root = build(0,n - 1,0,n - 1);
postOrder(root);
for(int i = 0;i < post.size();i++)
if(i == n - 1) cout<<post[i];
else cout<<post[i]<<" ";
return 0;
}