已知二叉树的先序和中序求后序

本文介绍如何通过先序和中序遍历构造二叉树,并提供了一段C++代码实现。文章详细解释了利用这两种遍历方式确定二叉树结构的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的根结点(根据三种遍历)只可能在左右(子树)之间,或这左子树的左边,或右子树的右边。
如果已知先序和中序(如果是中序和后序已知也可以,注意:如果是前序和后序的求中序是不可能实现的),先确定这棵二叉树。
步骤:1,初始化两个数组,存放先序合中序。
2,对比先序和中序,在中序忠查找先序的第一个元素,则在中序遍历中将这个元素的左右各元素分成两部分。即的左边的部分都在这个元素的左子树中,右边的部分都在右子树中。
3,然后从从先序的第二个元素开始继续上面的步骤。

如 先序:1 2 3 4 5 6 7 8 9 10 10
后序:3 2 5 4 1 7 9 8 11 10 6


level 1: 1
2: 2 3
3: 3 4 7
4: 5 8
5: 9 10
6: 11




这个太简单了,用个递归就可以,我到是有完整的代码,如下:
// tree.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "string.h"

typedef struct node
{
char data;
struct node *lchild,*rchild;
}BinNode;
typedef BinNode *BinTree;
BinNode *CreateNode(char c)
{
BinNode *n1=new BinNode;
n1->data=c;
n1->lchild=NULL;
n1->rchild=NULL;
return n1;
}
int searchchar(char c,char *order)
{
for(int i=0;i<strlen(order);i++)
{
if(c==order[i])
return i;

}
return -1;
}

BinNode* CreateTree(char *pre,char *in)
{
char c=pre[0];
char temppre[100];
char tempin[100];
char *p;
int i=0;
BinNode* bnode;
if(pre=='/0')
return NULL;

memset(temppre,0,100);
memset(tempin,0,100);

bnode=CreateNode(c);
i=searchchar(pre[0],in);
if(i==-1)
return 0;
p=in;
strncpy(tempin,p,i);
p=pre;
strncpy(temppre,p+1,i);
bnode->lchild=CreateTree(temppre,tempin);//left

memset(tempin,0,100);
memset(temppre,0,100);

p=in+i+1; 
strncpy(tempin,p,strlen(in)-i);
p=pre+i+1;
strncpy(temppre,p,strlen(in)-i);
bnode->rchild=CreateTree(temppre,tempin); //right
return bnode;
}

void POSTORDER(BinNode *t) 

if(t) /*二叉树t非空*/ 

POSTORDER(t->lchild); /*后序遍历*t的左子树*/ 
POSTORDER(t->rchild); /*后序遍历*t的右子树*/ 
printf("/t%c",t->data); /*访问结点*/ 



int main(int argc, char* argv[])
{
char preorder[100];
char inorder[100];

BinNode* Head;

do{
printf("请输入前序序列/n");
scanf("%s",preorder);
printf("请输入中序序序列/n");
scanf("%s",inorder);
}while(strlen(preorder)!=strlen(inorder));

Head=CreateTree(preorder,inorder);
printf("后序序列为:");
POSTORDER(Head);
printf("/n");
// printf("%ld",strlen(readin));
return 0;
<think>首,用户的问题是:“我想根据已知遍历遍历结果,出对应的后序遍历结果 请问如何从遍历遍历推导出后序遍历”。 我需要根据系统指令来构建回答: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 参考提供的引用: - 引用[1]:讨论了从二叉树的中后序推导,但用户需要的是从推导后序。 - 引用[2]:提到已知/后序与中出后/,但描述简略。 - 引用[3]:解释了二叉树的遍历顺。 - 引用[4]:包含代码示例,但可能与问题相关。 用户的问题是从遍历遍历推导后序遍历。所以,我需要解释这个过程。 关键点: - 遍历(Preorder):根节点 -> 左子树 -> 右子树 - 中遍历(Inorder):左子树 -> 根节点 -> 右子树 - 后序遍历(Postorder):左子树 -> 右子树 -> 根节点 推导步骤: 1. 从遍历中,第一个元素是根节点。 2. 在中遍历中,找到根节点,根节点左边的元素是左子树的中遍历,右边是右子树的中遍历。 3. 根据左子树的大小,在遍历中分割出左子树的遍历右子树的遍历。 4. 递归地对左子树右子树应用相同过程。 5. 构建后序遍历:左子树的后序,然后右子树的后序,最后根节点。 例如,假设: - :A B D E C F - 中:D B E A F C 步骤: 1. 第一个是A,所以根是A。 2. 中中,A左边是D B E(左子树),右边是F C(右子树)。 3. 左子树的:从中,A之后的下三个元素(因为左子树有3个节点),所以B D E。 4. 右子树的:剩下的C F。 5. 递归: - 左子树: B D E,中 D B E - 根是B,中中B左边是D(左子树),右边是E(右子树)。 - 左子树的后序:D(单节点) - 右子树的后序:E(单节点) - 所以左子树的后序:D E B - 右子树: C F,中 F C - 根是C,中中C左边是F(左子树) - 左子树的后序:F - 所以右子树的后序:F C 6. 整个树的后序:左子树后序 + 右子树后序 + 根 = D E B F C A 所以后序:D E B F C A 在回答中,我需要结构化: - 解释基础概念。 - 逐步描述方法。 - 可能给出一个简单例子。 - 确保使用正确的LaTeX格式。 - 生成相关问题。 生成相关问题: - 基于主题,例如:如何验证结果?处理边界情况?时间复杂度?优化方法?应用场景? 引用标识:在回答中,如果提到参考内容,自然地添加引用。例如,引用[3]解释了遍历顺,所以我可以说“如引用[3]所述”。 最终回答结构: 1. 介绍二叉树遍历基础。 2. 解释推导步骤。 3. 给出一个例子。 4. 总结。 5. 生成相关问题。</think>### 从遍历遍历推导后序遍历 在二叉树遍历中,已知遍历(Preorder)遍历(Inorder)列,可以唯一确定二叉树的结构,进而推导出后序遍历(Postorder)列。二叉树的遍历顺定义如下: - **遍历**:根节点 → 左子树 → 右子树(例如:$A, B, C$ 表示根为 $A$,左子树为 $B$,右子树为 $C$)。 - **中遍历**:左子树 → 根节点 → 右子树(例如:$B, A, C$ 表示左子树为 $B$,根为 $A$,右子树为 $C$)。 - **后序遍历**:左子树 → 右子树 → 根节点(例如:$B, C, A$ 表示左子树为 $B$,右子树为 $C$,根为 $A$)。 推导后序遍历的核心思想是利用遍历确定根节点,然后通过中遍历分割左右子树,最后递归构建子树并组合结果[^3]。以下是详细步骤: #### 推导步骤 1. **识别根节点**: 遍历的第一个元素总是整棵树的根节点。例如,给定列 $P = [p_1, p_2, \dots, p_n]$,根节点为 $p_1$。 2. **分割中列**: 在中遍历列 $I = [i_1, i_2, \dots, i_n]$ 中找到根节点 $p_1$ 的位置 $k$(即 $i_k = p_1$)。 - 根节点左边的子列 $I_{\text{left}} = [i_1, \dots, i_{k-1}]$ 是左子树的中遍历。 - 根节点右边的子列 $I_{\text{right}} = [i_{k+1}, \dots, i_n]$ 是右子树的中遍历。 3. **分割列**: 根据左子树的大小(即 $I_{\text{left}}$ 的长度 $L$),分割列: - 左子树的遍历:$P_{\text{left}} = [p_2, p_3, \dots, p_{L+1}]$(跳过根节点后,取前 $L$ 个元素)。 - 右子树的遍历:$P_{\text{right}} = [p_{L+2}, \dots, p_n]$(剩余元素)。 4. **递归构建子树**: 对左子树 $(P_{\text{left}}, I_{\text{left}})$ 右子树 $(P_{\text{right}}, I_{\text{right}})$ 递归应用上述步骤,得到左子树的后序遍历 $L_{\text{post}}$ 右子树的后序遍历 $R_{\text{post}}$。 5. **组合后序列**: 后序遍历列为左子树后序 + 右子树后序 + 根节点,即: $$ \text{Postorder} = L_{\text{post}} + R_{\text{post}} + [p_1] $$ 其中 $+$ 表示列连接。 #### 示例 假设给定: - 遍历:$P = [A, B, D, E, C, F]$ - 中遍历:$I = [D, B, E, A, F, C]$ 逐步推导: 1. **根节点**:第一个元素 $A$ 是根。 2. **分割中**:在中中找到 $A$,位置 $k=4$(索引从1开始)。 - 左子树中:$I_{\text{left}} = [D, B, E]$($A$ 左边) - 右子树中:$I_{\text{right}} = [F, C]$($A$ 右边) 3. **分割**:左子树大小 $L=3$($I_{\text{left}}$ 长度)。 - 左子树:$P_{\text{left}} = [B, D, E]$(跳过 $A$,取前3个) - 右子树:$P_{\text{right}} = [C, F]$(剩余元素) 4. **递归左子树**:$(P_{\text{left}} = [B, D, E], I_{\text{left}} = [D, B, E])$ - 根节点:$B$ - 中分割:$B$ 左边 $[D]$(左子树),右边 $[E]$(右子树) - 分割:左子树 $[D]$,右子树 $[E]$ - 递归结果:左子树后序 $[D]$,右子树后序 $[E]$,组合为 $[D, E, B]$ 5. **递归右子树**:$(P_{\text{right}} = [C, F], I_{\text{right}} = [F, C])$ - 根节点:$C$ - 中分割:$C$ 左边 $[F]$(左子树) - 分割:左子树 $[F]$ - 递归结果:左子树后序 $[F]$,组合为 $[F, C]$(无右子树) 6. **组合后序**:左子树后序 $[D, E, B]$ + 右子树后序 $[F, C]$ + 根 $A$ = $[D, E, B, F, C, A]$ 因此,后序遍历结果为 $[D, E, B, F, C, A]$。此方法的时间复杂度为 $O(n^2)$(最坏情况需线性搜索中位置),可通过哈希表优化到 $O(n)$[^2]。 #### 注意事项 - **唯一性**:二叉树必须无重复节点值,否则列可能对应多个树。 - **边界处理**:当子树为空时(列长度为0),直接返回空列。 - **验证**:推导后,可用中后序重建树来验证正确性,如引用[4]中的代码示例。 此方法基于二叉树遍历的递归特性,确保每一步都缩小问题规模[^1][^3]。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值