根据后序和中序遍历输出先序遍历(C语言)

该博客主要介绍了如何根据二叉树的后序遍历和中序遍历结果,通过递归算法求解先序遍历的过程。作者提出通过在后序遍历中找到根节点并划分左右子树,再递归地寻找左右子树的根节点,最终输出先序遍历序列。示例代码中包含了实现这一过程的两个关键函数:Find()用于寻找子树的根节点,gx()为递归函数,用于构造先序遍历序列。

本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值