首先说一下,只有 先序+中序——>后序,以及后序+中序——>前序,这两种推举方式,因为当只给出前序以及后序的遍历方式时,推得的中序是不唯一的,也就是不存在。
方法(核心):是根据每种遍历方式的特点,以前序遍历和后序遍历为基准,对中序遍历进行割裂(这里姑且称它为割裂法)。
这个要求我们对三种遍历方式 烂熟于心(必须透彻了解!!!)才能推得建树方式。这里给出两篇讲的很不错的博客 三种遍历方式详解、知二推三的粗略代码。
由于先序遍历的便捷性,中序遍历前序遍历推得后续遍历是比较容易的,所以这里只给出中+后——>前的代码。
一定要牢记上面所说的割裂方法,了解此方法后,这些代码是不必要记住的。
下面的代码同时对应了PTA的一道题目,这里给出题目以及AC代码;
7-1 根据后序和中序遍历输出先序遍历 (25 分)
本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数N(≤30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。
输出格式:
在一行中输出Preorder:
以及该树的先序遍历结果。数字间有1个空格,行末不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
Preorder: 4 1 3 2 6 5 7
AC代码(割裂法):
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int last[maxn],mid[maxn];
typedef struct node
{
int data;
node* left;
node* right;
}*BiTree;
node* solve(int *last,int *mid,int len)
{
if(len==0) return NULL;
int pos=0;
for(int i=0;i<len;i++)
{
if(mid[i]==last[len-1])
{
pos=i;
break;
}
}
BiTree nodes=new node();
nodes->data=mid[pos];
//构建左子树
nodes->left=solve(last,mid,pos);
//构建右子树
nodes->right=solve(last+pos,mid+pos+1,len-pos-1);
return nodes;
}
void Preorder(BiTree tree)//先序遍历
{
if(tree==NULL) return;
printf(" %d",tree->data);
Preorder(tree->left);
Preorder(tree->right);
}
int main()
{
int n; cin>>n;
for(int i=0;i<n;i++) cin>>last[i];
for(int i=0;i<n;i++) cin>>mid[i];
BiTree tree=solve(last,mid,n);
cout<<"Preorder:";
Preorder(tree);
return 0;
}