题目描述
给出一棵二叉树的中序遍历和前序遍历, 求出这棵二叉树的后序遍历。
输入格式
第一行: 树的中序遍历
第二行: 同样的树的前序遍历
ABEDFCHG
CBADEFGH
输出格式
单独的一行表示该树的后序遍历。
AEFDBHGC
题目分析: 首先要了解二叉树三种遍历的定义, 前序遍历: 首先访问根结点, 然后遍历左子树, 最后遍历右子树。中序遍历: 首先遍历左子树, 然后访问根结点, 最后遍历右子树。后序遍历: 首先遍历左子树, 然后遍历右子树, 最后访问根结点。
从以上对遍历的定义我们可以知道: 当前序遍历已知的情况下, 可以得到一棵二叉树的根结点——即为前序遍历的第一个元素。然后在中序遍历中找到根结点代表的元素, 往左便找到了左子树, 往右便找到了右子树 。但如何确定具体的算法呢?想一想二叉树遍历的过程, 本质上是深度优先搜索(DFS), 也就是递归的方式。所以可以自然地想到用递归算法进行求解。再根据后序遍历的定义: 先递归左子树, 再递归右子树, 最后访问根结点即可求得这棵二叉树的后序遍历
本题递归的核心在于找到左子树的前序、中序遍历的左右端点, 右子树的前序、中序遍历的左右端点(分别把前序遍历的左右端点记为, 中序遍历的左右端点记为
, 接下来会用样例的这棵二叉树进行分析:
首先找到根结点"C"(图中标注了root), 在中序遍历中, "C"左边的"ABEDF"为左子树, 右边的"HG"为右子树。然后确定左子树前序遍历的左端点, "C"的右边为"B", 是第一个在左子树中的元素, 所以左端点; 接下来确定右端点。在中序遍历中"C"的旁边是"F", 对应的下标为
, 所以距离=
, 所以右端点
。
接下来确定左子树中序遍历的左端点, 由于左端点本身就在左子树内, 所以不变, 而右端点
。
然后确定右子树前序遍历的左端点, 在中序遍历中, "C"的右边是"H", 对应的下标为, 所以距离=
, 所以左端点
, 右端点
不变。同理可得:
,
不变。
以下是代码
#include<bits/stdc++.h>
using namespace std;
string in_order,pre_order;
void build(int l1,int r1,int l2,int r2){
int i;
if(l1>r1||l2>r2) return;
for(i=l2;i<=r2;i++)
if(in_order[i]==pre_order[l1]){
build(l1+1,l1+i-l2,l2,i-1);
build(l1+i+1-l2,r1,i+1,r2);
cout<<in_order[i];
}
}
int main(){
int length;
cin>>in_order>>pre_order;
length=in_order.size();
build(0,length-1,0,length-1);
return 0;
}