题目为:
通过的代码为:
#include <iostream>
#include <cstring>
using namespace std;
void backi(string m,string f)
{
if(f.empty)//当前此为前序遍历序列分割出的左子树序遍历序列为空的时候,代表此子树已经分割完
return;
char s=f[0];//前序遍历序列的首位字符,即为此树枝的根节点
int i=m.find(s);//在中序遍历中找到此根节点的位置,已知根节点的两边分别为它的左右子树,以此分割区域
f.erase(f.begin());//抹去根节点,使得更好的分割
string lf=f.substr(0,i);//此为前序遍历序列分割出的左子树
string rf=f.substr(i);//此为前序遍历序列分割出的右子树
string lm=m.substr(0,i);//此为中序遍历序列分割出的左子树
string rm=m.substr(i+1);//此为中序遍历序列分割出的右子树
backi(lm,lf);backi(rm,rf);//在递归中将子树中的节点一步步分割,直到前序遍历序列为空,
//这代表以“前序遍历”得到的“根节点”已经在递
//归中得到,且可以按照后序遍历方式输出了。
cout <<s;
}
int main()
{
string mid,fro;
cin>>mid>>fro;//得到中序遍历和前序遍历序列
backi(mid,fro);//进入函数
return 0;
}
//这里解释一下为什么是从前序遍历中得出后序遍历的输出。
//可以知道,前序遍历是先输出节点再遍历左子树和右子树,即根左右,序列中
//以左优先,而后序遍历输出也是以左节点优先。前序遍历序列靠后的部分要么是前一个节点的子节点,
//要么就是一个节点同父节点的右儿子。
//以此为基本,则在中序遍历条件下判断左右子树,于是可以得到后序遍历序列
核心思路为:
从中序遍历序列中可得到根节点的左右子树,而已知前序序列的第一个节点为根节点。于是我们根据从中序遍历序列中得到的左右子树把前序遍历序列中的“左右子树”——就是包含着左右子树的串——截出来,使用递归,借助前序遍历序列的首字母总是根节点的特性一步步求出每一个截出的部分的“根节点”,最后使用后序遍历输出的方法,将得出的“根节点”输出即可。
递归中中序遍历序列用以计算出每个阶段的前序遍历序列的左右子树。仔细思考一下会发现,中序遍历序列和前序遍历序列的左右子树是有密切联系的。
其余实现重点在注释中有着重解释。