一、概述
题目只要求输出后序的首位,实际上输出整个后序遍历也差不多。
下面的代码即以输出整个后序为例分析。
二、分析
看题目可以得知最多有上万个节点,因此重建树方法不能用了,铁定超时。我们要选择直接输出后序的方法。
先看给出的:
前序遍历和中序遍历。
我们分析后序遍历,输出的第一个应该是从下往上从左往右第一个叶子节点,然后输出另一个叶子节点(如果有的话),然后输出它的父亲节点,然后输出另外一棵树,递归输出。
这样一来基本的逻辑就理清了。
代码如下:
void searchpost(int prel,int prer,int inl,int inr)
{
if(prel>prer)
{
return;
}
else if(prel==prer)
{
//if(first==-1)
//first=pre[prel];
printf("%d ",pre[prel]);
return;
}
int root=pre[prel];
int rootin=0;
for(int j=inl;j<=inr;j++)
{
if(in[j]==root)
{
rootin=j;
break;
}
}
int leftnum=rootin-inl;
//if(first!=-1)
//return;
searchpost(prel+1,prel+leftnum,inl,rootin-1);
//if(first!=-1)
//return;
searchpost(prel+leftnum+1,prer,rootin+1,inr);
printf("%d ",pre[prel]);
}
首先注意一点,返回和输出不一样,叶子节点要输出,叶子节点的父亲也要输出,因此当左大于右时,那就是遇到空节点的,左等于右时,是叶子节点。对于后一种,要先输出再return,前一种直接return。当叶子节点输出完,根节点也要输出。于是整个函数的逻辑如下:
判断;
整理;
去左子树;
去右子树;
输出根节点。
这样便可以实现输出后序了。
三、总结
本来以为会很麻烦,没想到实际上只不过是在函数最后加一行代码的事。
PS:代码如下:
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<string>
#include<cstring>
#include<math.h>
#include<algorithm>
using namespace std;
int pre[50010];
int in[50010];
int first=-1;
//为了找后序遍历的第一个,我们要找到最左下的那个
void searchpost(int prel,int prer,int inl,int inr)
{
if(prel>prer)
{
return;
}
else if(prel==prer)
{
if(first==-1)
first=pre[prel];
return;
}
int root=pre[prel];
int rootin=0;
for(int j=inl;j<=inr;j++)
{
if(in[j]==root)
{
rootin=j;
break;
}
}
int leftnum=rootin-inl;
if(first!=-1)
return;
searchpost(prel+1,prel+leftnum,inl,rootin-1);
if(first!=-1)
return;
searchpost(prel+leftnum+1,prer,rootin+1,inr);
}
int main()
{
int N;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d",&pre[i]);
}
for(int i=0;i<N;i++)
{
scanf("%d",&in[i]);
}
searchpost(0,N-1,0,N-1);
printf("%d",first);
}