#include<bits/stdc++.h>
using namespace std;
string in,post,pre;
void built(int in_l,int in_r,int post_l,int post_r)
{
	if(in_l>in_r) return ;//这总是排出这棵树只有一个节点的情况 

	char root=post[post_r];//根据后序树的定义找到根节点 
		pre+=root;//将根节点加入到先序遍历的字符串中 
		int root_post=0;//然后进行,找中序遍历树中根的位置 
	for(int i=0;i<=in_r;i++)
	if(in[i]==root)
	{
		root_post=i;//记录下根的位置
		break;
	}


	int l_num=root_post-in_l;//判断左子树节点的数目


     built(in_l,root_post-1,post_l,l_num+post_l-1);
//第一次对中+后序遍历左子树的处理(中序遍历树:0~i-1;  后序遍历树: 0~i-1)


     built(root_post+1,in_r,post_l+l_num,post_r-1);

//第一次对中+后序遍历右子树的处理(i+1  ~ in.size()-1;  i-1 ~ post.size()-1 ) 
}
int main()
{
	cin>>in>>post;//输入中序遍历、后序遍历
	built(0,in.size()-1,0,post.size()-1);//中序遍历和后续遍历的起始位置 
	cout<<pre<<endl;//对结果进行输出
	return 0;
}

总结:

1. 根节点的正确定位
  • 后序遍历的最后一个元素必定是当前子树的根节点,这是解题的核心。
  • 若后序序列为空(in_l > in_r),直接返回。
2. 中序序列分割的正确性
  • 在中序序列中查找根节点时,必须遍历当前子树的范围in_l 到 in_r),而非整个中序序列。
  • 错误示例:原代码中 for (int i = 0; i < in_r; i++) 错误地从 i=0 开始遍历,导致根节点位置错误。
3. 后序序列分割的索引计算
  • 左子树后序范围:起始索引为 post_l,结束索引为 post_l + left_num - 1left_num 是左子树节点数)。
  • 右子树后序范围:起始索引为 post_l + left_num,结束索引为 post_r - 1(根节点不包含在右子树中)。
  • 错误示例:若未正确计算索引,可能导致递归时传入错误的后序范围,引发数组越界或逻辑错误。
4. 递归终止条件
  • 当 in_l > in_r 时,表示当前子树为空,直接返回,避免无限递归。
5. 特殊情况处理
  • 单节点树:当 in_l == in_r 时,直接将根节点加入先序序列即可。
  • 左右子树为空:例如,根节点只有左子树或右子树时,递归会自动处理空的情况。
6. 代码实现细节
  • 变量命名:清晰的变量名(如 in_lpost_r)可提高代码可读性。
  • 循环条件:确保循环覆盖当前子树的完整范围(i <= in_r),而非仅到 i < in_r
  • 递归参数传递:严格匹配中序和后序的分割范围,确保左右子树的递归调用正确。

Logo

集算法之大成!助力oier实现梦想!

更多推荐