【天梯赛】L2-006. 树的遍历(层次遍历)

题目描述:

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2

题目思路:

如果题目说,给出后序遍历和中序遍历,求先序遍历,那么你一定会做(如果不会做,可以先学会如何通过中序+后序,求先序,然后再来学习本题)。现在题目的前提条件不变,但是求的是层次遍历。当然你可以通过后序和中序建树,然后用BFS输出层次遍历的结果。这里我采用的是在递归函数中添加一个参数index来表示当前递归层次中根节点应该在树中的坐标(层次遍历的坐标)。

题目中给出的数据的二叉树如图所示。

递归的过程如图所示:


我们可以看出每次递归左子树的时候,左子树的根节点在层次遍历中的坐标是2*index+1,(我们假设左子树根节点的父亲结点的坐标是index。如:图中权值为1的结点和权值为4的结点的关系)。同理右子树在层次遍历中的坐标是2*index+2。因此我们可以新开辟一个数组在递归的过程中,每个结点在层次遍历中的位置,最后输出该数组即可。需要注意的是,如果二叉树的结点有n个,那么最多有n层,最少有log2(n+1)层,因此数组最大需要开2^30-1个。如果给定7个结点,那么他最多有七层,显示,我们在输出心声明的数组的时候,不能只输出前7个的值,因为最后一个结点的坐标是2^7-2。


题目代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 10000
using namespace std;

int s1[MAXN], s2[MAXN], s3[MAXN];
int n;
/*
	p1 p2 q1 a2 表示两种遍历结果的起始位置
	index表示当前根节点在二叉树中的位置(层次遍历) 
*/
void f(int p1, int p2, int q1, int q2, int index)
{
	if(p1>p2 || q1>q2) return ;
	
	int i = p1 ;
	while(s1[i] != s2[q2]) i++;
	s3[index] = s1[i];
	//left
	f(p1, i-1, q1, q1+i-1-p1, 2*index+1);
	//right
 	f(i+1, p2, q1+i-p1, q2-1, 2*index+2);
	
}

int main()
{
	cin>>n;
	for(int i=0; i<n; i++) cin>>s2[i];
	for(int i=0; i<n; i++) cin>>s1[i];
	memset(s3,0,sizeof(s3));
	f(0, n-1, 0, n-1, 0);
	//cnt用来记录有效数字的个数 
	int cnt = 0; 
	for(int i=0; i<=100000; i++) {
		if(cnt==n)break;
		if(s3[i]){
			cnt++;
			if(i)cout<<" ";
			cout<<s3[i];
		}
	}
	return 0;
}



  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值