求后序遍历

#include <bits/stdc++.h>
using namespace std;
string s1,s2;
void calc(int l1,int r1,int l2,int r2)
{
int m=s2.find(s1[l1]);
if(m>l2) calc(l1+1,l1+m-l2,l2,m-1);
if(m<r2) calc(l1+m-l2+1,r1,m+1,r2);
cout<<s1[l1];
}
int main()
{
cin>>s1>>s2;
calc(0,s1.length()-1,0,s2.length()-1);
cout<<endl;
return 0;
}
<think>我们已知二叉树的先序遍历和中序遍历后序遍历。 先序遍历:KDCEFGHB 中序遍历:CDFEGHKB 方法步骤: 1. 先序遍历的第一个节点是整棵树的根节点。所以根节点是 K。 2. 在中序遍历中找到根节点 K,则根节点左边的部分是左子树的中序遍历,右边的部分是右子树的中序遍历。 中序遍历:CDFEGHKB -> 在K左边的是 CDFEGH,右边的是 B。 因此,左子树的中序遍历为:C D F E G H (注意,这里是一个序列,共6个节点) 右子树的中序遍历为:B(1个节点) 3. 根据左子树和右子树的节点数量,可以在先序遍历中划分左右子树。 先序遍历:根节点K之后,先遍历左子树,再遍历右子树。 左子树的节点数为6,所以先序遍历中根节点K之后的6个节点(D C E F G H)是左子树的先序遍历。 注意:这里先序遍历是KDCEFGHB,所以去掉K后,剩下DCEFGHB,我们取前6个作为左子树的先序遍历:DCEFGH,剩下的B就是右子树的先序遍历。 但是,注意观察:先序遍历序列KDCEFGHB,K之后是D,然后C,然后E...所以左子树的先序遍历是DCEFGH(6个节点),右子树就是B。 4. 现在问题分解为: 左子树:先序遍历为 D C E F G H,中序遍历为 C D F E G H。 右子树:先序遍历为 B,中序遍历为 B。 5. 对于右子树:只有一个节点B,所以它的后序遍历就是B。 6. 对于左子树,我们继续递归: 左子树的先序遍历:D C E F G H 左子树的中序遍历:C D F E G H 左子树的根节点是先序遍历的第一个节点:D。 在中序遍历中找到D的位置:C D FEGH -> D左边是C(左子树),右边是F E G H(右子树)。 因此,D的左子树的中序遍历:C(1个节点) D的右子树的中序遍历:F E G H(4个节点) 根据先序遍历:在根D之后,先遍历左子树,再遍历右子树。 D之后第一个节点是C,然后是E F G H。 因为左子树只有1个节点,所以左子树的先序遍历就是C(1个节点),右子树的先序遍历就是E F G H(4个节点)。 所以: D的左子树:先序遍历为C,中序遍历为C -> 后序遍历为C。 D的右子树:先序遍历为E F G H,中序遍历为F E G H。 现在处理D的右子树(先序:E F G H,中序:F E G H): 根节点是先序遍历的第一个节点:E。 在中序遍历中找到E:F E G H -> E左边是F(左子树),右边是G H(右子树)。 所以: E的左子树:先序遍历:F(因为先序中E之后第一个是F,并且左子树只有1个节点),中序遍历:F -> 后序遍历:F。 E的右子树:先序遍历:G H(E之后去掉左子树的F,剩下GH),中序遍历:G H。 处理E的右子树(先序:G H,中序:G H): 根节点:G。 中序遍历:G H -> G左边为空,右边为H(右子树)。 所以: G的左子树为空,右子树:先序遍历H(因为先序中G之后是H),中序遍历H -> 后序遍历:H。 G的右子树后序遍历为H,所以以G为根的树的后序遍历为:左(空)+右(H)+根 -> H G。 因此,E的右子树的后序遍历为:H G。 然后,E的整个树的后序遍历:左子树的后序遍历(F) + 右子树的后序遍历(HG) + 根(E) -> F H G E。 所以D的右子树的后序遍历为:F H G E。 最后,D的整个树的后序遍历:左子树(C) + 右子树(FHGE) + 根(D) -> C F H G E D。 7. 因此,左子树的后序遍历为:C F H G E D (注意:我们上面得到的是CFHGED)。 8. 现在回到整棵树: 后序遍历 = 左子树的后序遍历 + 右子树的后序遍历 + 根节点 = CFHGED + B + K = CFHGEDBK 所以后序遍历结果为:CFHGEDBK 验证: 先序遍历:K->D->C->E->F->G->H->B (KDCEFGHB) 中序遍历:C->D->F->E->G->H->K->B (CDFEGHKB) 后序遍历:C->F->H->G->E->D->B->K (CFHGEDBK) 注意:在D的右子树部分,中序遍历是FEGH,但在递归处理时,我们分解为F(左)和GH(右),而GH在中序遍历中实际上是连续的,所以正确。 因此,最终后序遍历结果为:CFHGEDBK 但是,我们写的时候要注意顺序:后序遍历是左子树、右子树、根。每一步都要按这个顺序合并。 </think>### 根据先序遍历和中序遍历后序遍历的方法 #### 核心原理 二叉树遍历的三种顺序具有以下特征(引用[^1][^2]): 1. **先序遍历**:根节点 → 左子树 → 右子树 2. **中序遍历**:左子树 → 根节点 → 右子树 3. **后序遍历**:左子树 → 右子树 → 根节点 通过先序定位根节点,结合中序划分左右子树,即可递归重建二叉树(引用[^3][^4])。 --- #### 解步骤(以题为例) **已知**: - 先序遍历:$\text{KDCEFGHB}$ - 中序遍历:$\text{CDFEGHKB}$ 1. **确定根节点** 先序的首字符是根节点:$K$ (引用[^3]:先序遍历的第一个节点必为根节点) 2. **划分左右子树** 在中序中找到 $K$: - 左侧 $\text{CDFEGH}$ → 左子树(6节点) - 右侧 $\text{B}$ → 右子树(1节点) (引用[^4]:中序遍历中根节点左侧为左子树,右侧为右子树) 3. **递归处理左子树** - 左子树先序:$\text{DCEFGH}$(从根 $K$ 后取6字符) - 左子树中序:$\text{CDFEGH}$ - 子根节点:$D$(先序首字符) - 中序划分:$C$(左)和 $FEGH$(右) - 递归结果:左子树后序 = $\text{CFHGED}$ 4. **递归处理右子树** - 右子树先序:$\text{B}$ - 右子树中序:$\text{B}$ - 递归结果:右子树后序 = $\text{B}$ 5. **合并后序遍历** 后序 = 左子树后序 + 右子树后序 + 根节点 $\boxed{\text{CFHGEDBK}}$ (引用[^2]:后序遍历需最后访问根节点) --- #### 伪代码实现 ```python def build_postorder(preorder, inorder): if not preorder: return "" root = preorder[0] # 1. 取根节点 idx = inorder.index(root) # 2. 定位根在中序位置 # 3. 递归左右子树 left_in = inorder[:idx] # 左子树中序 right_in = inorder[idx+1:] # 右子树中序 left_pre = preorder[1:1+len(left_in)] # 左子树先序 right_pre = preorder[1+len(left_in):] # 右子树先序 # 4. 合并结果:左子树后序 + 右子树后序 + 根 return build_postorder(left_pre, left_in) + \ build_postorder(right_pre, right_in) + \ root # 示例调用 postorder = build_postorder("KDCEFGHB", "CDFEGHKB") # 输出 "CFHGEDBK" ``` --- #### 关键点说明 1. **子树划分**:中序序列的长度决定先序中子树的范围(引用[^4])。 2. **递归终止**:当子树为空时返回空字符串。 3. **时间复杂度**:$O(n^2)$(每次递归需遍历中序序列),可通过哈希表优化到$O(n)$[^1]。 4. **唯一性**:只要节点值不重复,二叉树可唯一确定(引用[^3])。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值