[刷题之旅no22]P1827 [USACO3.4]美国血统 American Heritage

这篇博客介绍了如何通过递归方法,利用给定的树的中序和前序遍历序列来重构树的后序遍历。文章详细阐述了递归过程,包括找到根节点、计算子树长度、递归子树以及终止条件的判断。作者还特别强调了递归中变量的作用域和管理,以及递归终止条件的正确设置对于避免逻辑错误的重要性。
摘要由CSDN通过智能技术生成

其实这道题,就是给出树的中序遍历和前序遍历,让你写出他的后续遍历哈哈
话说这道题跟之前的有点像啊。。
思路就是递归
别忘了左右边界的变化,上次你在这栽了坑
递归函数,
1.前序左端点找到根节点
2.中序序列之中找到根节点,记录其坐标
3.根据中序序列坐标和左右端点,计算左右子树长度,找到左坐标范围
4.在前序序列中找到找到左右子树的坐标范围
5.左子树递归,右子树递归
6.打印根节点
7.结束
递归结束条件。
左右端点相等,说明只剩一个点了
好吧,看来又出现了我最害怕的逻辑出错了,这些下标算起来真是有点烦人
而且终止条件看起来很难判断啊。。
重要的错误!:
对于我的递归学习有很大的帮助
对于递归中的变量,如果需要记录,那么请把变量设置成全局变量
但是如果有多次连续递归都需要用到一个变量,并且需要这个变量只在这层递归有效,那么请设置在这个函数内部
比如这道题中的root和proot
由于下面有左右子树的双层递归,如果设在外面,那么左子树递归之后,再return回来的时候,
root和proot就不是原来的值了!
当然我们纠结的递归终止条件,就是
if(左>=右)
{
if(左==右)
{
输出
}
return 0;
/即可/
}
附代码:

#include<stdio.h>
#include<string.h>
char midt[27],head[27];
int length=0;
void dfs(int ml,int mr,int hl,int hr); 
int main()
{
	scanf("%s",midt);
	scanf("%s",head);
	length=strlen(midt);
	dfs(0,length-1,0,length-1);
	return 0;
}

void dfs(int ml,int mr,int hl,int hr)
{
	char root;
	int proot=0;
	if(ml>mr||hl>hr)
	{
		return ;
	}
	if(ml==mr||hl==hr)
	{
		printf("%c",midt[ml]);
		return ;
	}
	root=head[hl];//取出根节点
	for(int i=ml;i<=mr;i++)
	{
		if(midt[i]==root)
		{
			proot=i;//找到根节点的位置 
			break;
		}
	}
	//计算左右子树的下标.然后进行递归
//	printf("dfs(%d,%d,%d,%d):\n",ml,proot-1,hl+1,hl+proot-ml);
//	printf("proot=%d,ml=%d,mr=%d,hl=%d,hr=%d\n",proot,ml,mr,hl,hr);
//	printf("当前根节点:%c\n",midt[proot]);
	dfs(ml,proot-1,hl+1,hl+proot-ml);
//	printf("dfs(%d,%d,%d,%d)\n",proot+1,mr,hl-ml+proot+1,hr);
//	printf("当前根节点:%c\n",midt[proot]);
//	printf("proot=%d,ml=%d,mr=%d,hl=%d,hr=%d\n",proot,ml,mr,hl,hr);
	dfs(proot+1,mr,hl+proot-ml+1,hr);
	printf("%c",root);
	return ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值