本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数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
思路:
其实就是将已知中序遍历和后序遍历后求先序遍历的思路转换成代码(好像说了句废话。。)
我拿到题目所给的中序遍历和后序遍历后,会在后续遍历中找到整棵树的根结点,也就是后序遍历最后一个结点值将其输出
然后通过此根结点在中序遍历中划分出左子树和右子树,接下来重复步骤,在后序遍历中找到左子树的根结点,将其输出,直到左子树中最后一个结点没有他自己的左子树和右子树,结束递归,然后开始对右子树进行同样的方法
所以我认为可以写两个函数
一个是在后序遍历中找出中序遍历中某一序列的根结点,想法是比对序列的和是否相同(时间复杂度很糟糕。。)
另一个就是递归函数,结束条件为某一结点没有他自己的左子树和右子树
#include<stdio.h>
static int c = 0;
int Find(int sum,int pos[],int in[],int N,int length){//用来找到中序序列中的左子树或右子树的根节点
int sum_ = 0,i,i_;//记录后序序列中的子序列和
int count = 0;//用来记录暴力求解序列元素的个数
for(i = 0,i_ = 0;i < N;i++){
if(!sum_){
i = i_;
i_++;//记录sum_序列的起始位置
}
count++;
sum_ += pos[i];
if(sum_ == sum&&count == length)
break;//且此时的序列即为i_--i
else if((count == length&&sum_ != sum)||sum_ > sum)
sum_ = count = 0;
}
for(i_ = 0;pos[i] != in[i_];i_++);
return i_;//返回根节点在中序序列中的位置
}
void gx(int low,int high,int mid,int pos[],int in[],int N){
int sum = 0,i;
c++;
if(c != N)
printf("%d ",in[mid]);
else
printf("%d",in[mid]);
if(low < mid){
for(i= 0;low+i < mid;i++)
sum += in[low+i];
gx(low,mid-1,Find(sum,pos,in,N,i),pos,in,N);
}
sum = 0;
if(high > mid){
for(i= 1;mid+i <= high;i++)
sum += in[mid+i];
gx(mid+1,high,Find(sum,pos,in,N,i-1),pos,in,N);
}
}
int main()
{
int N;//结点个数
scanf("%d",&N);
int in[N];//中序遍历inorder
int pos[N];//后序遍历postorder
int i,i_;
for(i = 0;i < N;i++)
scanf("%d",&pos[i]);
for(i = 0;i < N;i++)
scanf("%d",&in[i]);
/*以上完成题目的输入*/
printf("Preorder: ");
for(i = 0;pos[N-1] != in[i];i++);
gx(0,N-1,i,pos,in,N);
}
该博客主要介绍了如何根据二叉树的后序遍历和中序遍历结果,通过递归算法求解先序遍历的过程。作者提出通过在后序遍历中找到根节点并划分左右子树,再递归地寻找左右子树的根节点,最终输出先序遍历序列。示例代码中包含了实现这一过程的两个关键函数:Find()用于寻找子树的根节点,gx()为递归函数,用于构造先序遍历序列。
&spm=1001.2101.3001.5002&articleId=116402610&d=1&t=3&u=365689a915a04ee0a11718350277f2b7)
4425

被折叠的 条评论
为什么被折叠?



