洛谷P1030 [NOIP 2001 普及组] 求先序排列
·


#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 - 1(left_num是左子树节点数)。 - 右子树后序范围:起始索引为
post_l + left_num,结束索引为post_r - 1(根节点不包含在右子树中)。 - 错误示例:若未正确计算索引,可能导致递归时传入错误的后序范围,引发数组越界或逻辑错误。
4. 递归终止条件
- 当
in_l > in_r时,表示当前子树为空,直接返回,避免无限递归。
5. 特殊情况处理
- 单节点树:当
in_l == in_r时,直接将根节点加入先序序列即可。 - 左右子树为空:例如,根节点只有左子树或右子树时,递归会自动处理空的情况。
6. 代码实现细节
- 变量命名:清晰的变量名(如
in_l,post_r)可提高代码可读性。 - 循环条件:确保循环覆盖当前子树的完整范围(
i <= in_r),而非仅到i < in_r。 - 递归参数传递:严格匹配中序和后序的分割范围,确保左右子树的递归调用正确。
更多推荐



所有评论(0)