原题链接
前中后序遍历的差别大家都知道,就不再赘述了。
根据后序遍历的特性,我们知道最后一个输出的结点,在题目样例中是A,是这棵二叉树的根节点。再根据中序遍历的特性,在根节点左边输出的结点都是左子树的结点,在根节点右边输出的结点都是右子树的结点。也就是说,B是根节点的左子树的结点,DC是根节点的右子树的结点。递归地,我们容易还原出这棵二叉树。
在我们判断A是根节点的时候,显然A是前序遍历的第一个输出结点,我们将其输出。递归地,可以得出整个前序遍历的输出顺序。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 10;
char pre[MAXN];//前序遍历的顺序
char in[MAXN];//中序遍历的顺序
char past[MAXN];//后序遍历的顺序
int size;//这颗二叉树的结点数
int p=0;//指向目前待更新的pre数组的下标
char last(int l, int r, int*n)//返回中序数组的[l,r]区间中在后序数组中最后出现的结点
{
for(int i=size-1; i>=0; i--)//从后往前地遍历后序数组
for(int j=l; j<=r; j++)//遍历中序数组的[l,r]区间
if(past[i] == in[j]) //如果相等意味着in[j]是[l,r]区间最后一个出现在后序数组中的
{
*n = j;//把j结点的下标传回solution函数
return in[j];
}
}
void solution(int l, int r) //l和r确定中序数组的一个区间
{
if(l == r)//如果相等,说明in[l]可以直接放进pre里面
{
pre[p++] = in[l];
return;
}
else if(l > r) return;//此时显然不论是in[l]还是in[r]都处理过了,直接返回就行了
int mid;//用于记录该子树的根节点
pre[p++] = last(l,r,&mid); //把该子树的根节点写入前序遍历
solution(l,mid-1);//递归左子树
solution(mid+1,r);//递归右子树
//这两个递归调的顺序不可以调换,因为先序遍历一定是先遍历左子树再遍历右子树
}
int main()
{
scanf("%s %s",in,past);
size = strlen(in);
p=0;
solution(0,size-1);
for(int cnt=0; cnt<size; cnt++)
putchar(pre[cnt]);
putchar('\n');
return 0;
}