原题链接
题目描述
假定一棵二叉树的每个结点都用一个大写字母描述。
给定这棵二叉树的前序遍历和中序遍历,求其后序遍历。
输入格式
输入包含多组测试数据。
每组数据占两行,每行包含一个大写字母构成的字符串,第一行表示二叉树的前序遍历,第二行表示二叉树的中序遍历。
输出格式
每组数据输出一行,一个字符串,表示二叉树的后序遍历。
数据范围
输入字符串的长度均不超过 26。
输入样例:
ABC
BAC
FDXEAG
XDEFAG
输出样例:
BCA
XEDGAF
题目分析
这个题目是经典的二叉树遍历问题。
首先应知道先序遍历、中序遍历和后续遍历的概念。
- 先序遍历:按照根节点、左子树、右子树的顺序。
- 中序遍历:按照左子树、根节点、右子树的顺序。
- 后序遍历:按照左子树、右子树、根节点的顺序。
题目给出了先序遍历和中序遍历,要求后序遍历。
对于一个二叉树,我们首先要确定它的根节点,而先序遍历的第一个元素就是根节点。
其次要确定左子树的元素和右子树的元素。根据根节点,通过中序遍历就可以找到左子树、右子树的元素。具体操作如下:
- 查找根节点在中序遍历中的位置K
- 位于位置K左边的全部为左子树的元素
- 位于位置K右边的全部为右子树的元素
如上操作,可以确定二叉树的根节点,左子树元素,右子树元素。也就是左子树元素和右子树元素的中序遍历。
最后找到左子树和右子树的前序遍历,然后递归求解后续遍历序列即可。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
//递归函数,求解后续遍历
string dfs(string preorder, string inorder){
string postorder;//后序遍历的结果
if(preorder.empty())//前序遍历序列为空,返回空串
return postorder;
int k = inorder.find( preorder[0] );//查找根节点在中序遍历中的位置
//递归求解左子树的后续遍历
/*
substr(pos, len)函数为string库的库函数,作用是复制子字符串。
s.substr(pos,len);表示从s字符串的第pos位开始,复制len长度个子字符串。
s.substr(pos);若第二个参数缺省,则表示从pos开始,一直复制到s字符串结束。
*/
string l_postorder = dfs( preorder.substr( 1, k ), inorder.substr( 0, k));
//递归求解右子树的后续遍历
string r_postorder = dfs( preorder.substr( k + 1), inorder.substr( k + 1 ));
//拼接字符串,返回整个二叉树的后续遍历序列
postorder = l_postorder + r_postorder + preorder[0];
return postorder;
}
int main(){
string preorder, inorder, postorder;
//读到EOF文件结束符是,返回0
while(cin >> preorder >> inorder){
postorder = dfs(preorder, inorder);
cout << postorder << endl;
}
return 0;
}