本题来源于洛谷,题目要求根据一颗二叉树的中序和后序遍历,输出二叉树的先序遍历。
题目描述
给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,且二叉树的节点个数 ≤ 8 \le 8 ≤8)。
输入格式
共两行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。
输出格式
共一行一个字符串,表示一棵二叉树的先序。
解题思路
树是一种具有递归定义的数据结构,也可以看成一个无环图。
下面将介绍两种写法:
- 在递归过程中直接输出先序遍历
- 根据中序和后序遍历构造一棵二叉树,然后使用深度优先搜索遍历出二叉树的先序遍历(主要是有的题目不会直接让我们求先序遍历,而是先构造出二叉树,然后再进行别的操作)
思考过程
中序遍历二叉树的顺序:
- 遍历左子树
- 遍历根节点
- 遍历右子树
后序遍历二叉树的顺序:
4. 遍历左子树
5. 遍历右子树
6. 遍历根节点
所以我可以确定,后序遍历的最后一个节点一定是整个二叉树的根节点,所以根据这个根节点的在中序遍历中的位置,将中序遍历分为这个根节点的左子树和右子树。
递归的有,我们依次根据后序遍历重复上述过程,最终可以得到二叉树的前序遍历。
步骤:
- 找根节点
- 确定根节点在中序遍历中的位置
- 递归的求左子树
- 递归的求右子树
需要注意的一点,这个是二叉树的知识,我们每一轮是针对一个节点来说的,它的左子树和右子树在前序遍历和后序遍历中的节点数量是一致的。
方法一:
#include <iostream>
#include <string>
using std::cin;
using std::ios;
using std::cout;
using std::endl;
using std::string;
void printPreorder(string, string);
int main(int argc, char **argv){
ios::sync_with_stdio(false);
string inorder;
string postorder;
cin >> inorder;
cin >> postorder;
printPreorder(inorder, postorder);
return 0;
}
void printPreorder(string inorder, string postorder){
if(postorder.length() <= 0){
return;
}
char root = postorder[postorder.length() - 1];
cout << root;
int pos = inorder.find(root);
printPreorder(inorder.substr(0, pos), postorder.substr(0, pos));
printPreorder(inorder.substr(pos+1), postorder.substr(pos, inorder.length() - pos - 1));
}
方法二
和方法一思路基本是一样的:
- 根据后序遍历找根节点
- 在中序遍历中找根节点的位置
- 构造根节点
- 递归构造该节点的左子树
- 递归构造该节点的右子树
- 返回根节点
#include <iostream>
#include <string>
using std::cin;
using std::ios;
using std::cout;
using std::endl;
using std::string;
typedef struct Node{
char value_;
Node *right_;
Node *left_;
Node(char, Node*, Node*);
~Node();
}Node;
Node::Node(char value, Node *right = nullptr, Node *left = nullptr){
value_ = value;
right_ = right;
left_ = left;
}
Node::~Node(){
if(right_ != nullptr){
delete right_;
right_ = nullptr;
}
if(left_ != nullptr){
delete left_;
left_ = nullptr;
}
}
Node* build(const string&, const string&);
void preTraverse(Node*);
int main(int argc, char **argv){
ios::sync_with_stdio(false);
string inorder;
string postorder;
cin >> inorder;
cin >> postorder;
Node *root = build(inorder, postorder);
preTraverse(root);
return 0;
}
Node* build(const string& inorder, const string& postorder){
if(postorder.length() <= 0){
return nullptr;
}
char r = postorder[postorder.length() - 1];
int pos = inorder.find(r);
Node *root = new Node(r);
//构造左子树
root->left_ = build(inorder.substr(0, pos), postorder.substr(0, pos));
//构造右子树
root->right_ = build(inorder.substr(pos+1), postorder.substr(pos, inorder.length() - pos - 1));
return root;
}
void preTraverse(Node* root){
if(root == nullptr){
return;
}
cout << root->value_;
preTraverse(root->left_);
preTraverse(root->right_);
}
做完这题可以尝试一下 UVA548