题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
思路:
先序遍历的第一个节点即为根结点,而中序遍历中,该节点左边的节点为左子树节点,右边的为右子树的节点,因此根据这些节点区间可以确定出先序遍历中左右子树节点范围,然后这些子区间也满足上述性质,递归求解即可。
知道中序遍历和后序遍历,也可以确定整棵二叉树,只是后序遍历的最后一个节点为二叉树的根结点,实现起都差不多,在这里我也顺便实现了一下。。
#include <cstdio>
#include <cstring>
using namespace std;
typedef struct Node{
int val;
Node* left;
Node* right;
Node(int val) : val(val), left(NULL), right(NULL) {}
} *pNode;
class BT{
private:
pNode root;
bool Pre_In_Build(pNode *, int *, int, int, int *);//根据先序遍历和中序遍历求二叉树
bool In_Post_Build(pNode *, int *, int, int, int *);//根据中序遍历和后序遍历求二叉树
void post_Traverse(pNode);
void pre_Traverse(pNode);
void Delete_BT(pNode);
public:
bool Pre_In_Build(int *, int, int, int *);//先序遍历数组,数组大小,中序遍历起始位置,中序遍历各元素下标
bool In_Post_Build(int *, int, int, int *);//后序遍历数组,数组大小,中序遍历起始位置,中序遍历各元素下标
void post_Traverse();
void pre_Traverse();
BT();
~BT();
};
bool BT::Pre_In_Build(int *pre, int pre_n,int in_start_pos, int *in_pos){
return Pre_In_Build(&this->root, pre, pre_n, in_start_pos, in_pos);
}
bool BT::Pre_In_Build(pNode *node, int *pre, int pre_n, int in_start_pos, int *in_pos){
if(pre_n == 0){
*node = NULL;
return true;
}
*node = new Node(pre[0]);
if(in_pos[pre[0]] > in_start_pos + pre_n - 1 || in_pos[pre[0]] < in_start_pos)
return false;
int len = in_pos[pre[0]] - in_start_pos;
bool flag1 = Pre_In_Build(&((*node)->left), pre + 1, len, in_start_pos, in_pos);
bool flag2 = Pre_In_Build(&((*node)->right), pre + len + 1, pre_n - len - 1, in_start_pos + len + 1, in_pos);
return flag1 && flag2;
}
bool BT::In_Post_Build(int *post, int post_n, int in_start_pos, int *in_pos){
return In_Post_Build(&this->root, post, post_n, in_start_pos, in_pos);
}
bool BT::In_Post_Build(pNode *node, int *post, int post_n, int in_start_pos, int *in_pos){
if(post_n == 0){
*node = NULL;
return true;
}
*node = new Node(post[0]);
if(in_pos[post[0]] > in_start_pos + post_n - 1 || in_pos[post[0]] < in_start_pos)
return false;
int len = in_pos[post[0]] - in_start_pos;
bool flag1 = In_Post_Build(&((*node)->right), post + 1, post_n - len - 1, in_start_pos + len + 1, in_pos);
bool flag2 = In_Post_Build(&((*node)->left), post + (post_n - len), len, in_start_pos, in_pos);
return flag1 && flag2;
}
void BT::pre_Traverse(){
pre_Traverse(this->root);
}
void BT::pre_Traverse(pNode node){
if(node){
printf("%d ", node->val);
pre_Traverse(node->left);
pre_Traverse(node->right);
}
}
void BT::post_Traverse(){
post_Traverse(this->root);
}
void BT::post_Traverse(pNode node){
if(node){
post_Traverse(node->left);
post_Traverse(node->right);
printf("%d ", node->val);
}
}
void BT::Delete_BT(pNode node){
if(node){
Delete_BT(node->left);
Delete_BT(node->right);
delete node;
}
}
BT::BT(){
root = NULL;
}
BT::~BT(){
Delete_BT(this->root);
}
int main()
{
int n;
int *pos = new int[1001];
int *pre = new int[1001];
int *in = new int[1001];
int *post = new int[1001];
while(scanf("%d", &n) != EOF){
BT *bt = new BT;
memset(pos, 0x7fffffff, sizeof(int) * 1001);
for(int i = 0; i < n; i++){
scanf("%d", &pre[i]);
}
for(int i = 0; i < n; i++){
scanf("%d", &in[i]);
pos[in[i]] = i;
}
// for(int i = n-1; i >= 0; i--){
// scanf("%d", &post[i]);
// }
if(bt->Pre_In_Build(pre, n, 0, pos)){
bt->post_Traverse();
printf("\n");
}
// if(bt->In_Post_Build(post, n, 0, pos)){
// bt->pre_Traverse();
// printf("\n");
// }
else{
printf("No\n");
}
delete bt;
}
delete[] pos;
delete[] pre;
delete[] in;
return 0;
}
/*
6
1 6 4 3 5 2
1 4 6 5 2 3
*/