根据中序遍历和后序遍历求二叉树的先序遍历

本文介绍了一种根据给定的中序和后序遍历序列重构二叉树并求得先序遍历序列的方法。通过递归创建二叉树节点,并采用先序遍历输出结果,适用于计算机科学中的数据结构学习。

求二叉树的先序遍历

Time Limit: 1000MS Memory limit: 65536K

题目描述

 已知一棵二叉树的中序遍历和后序遍历,求二叉树的先序遍历

输入

 输入数据有多组,第一行是一个整数t (t<1000),代表有t组测试数据。每组包括两个长度小于50 的字符串,第一个字符串表示二叉树的中序遍历序列,第二个字符串表示二叉树的后序遍历序列。

输出

 输出二叉树的先序遍历序列

示例输入

2
dbgeafc
dgebfca
lnixu
linux

示例输出

abdegcf
xnliu
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 50+3

struct bitree
{
    char data;//数据
    struct bitree *lchild;//左孩子
    struct bitree *rchild;//右孩子
};      //要查找的元素  查找的地方    数组的长度
int search_num(char num, char *array,int len)
{
    int i;
    for( i=0; i<len; i++)
       if(array[i] == num)
         return i;
    return -1;//没有找到
}                           //中序遍历    后序遍历     中序长度
struct bitree *Resume_bitree(char *center,char *back,int len)
{
    if(len <= 0)
      return NULL;
    struct bitree *temp ;
    temp =(struct bitree*)malloc(sizeof(struct bitree));
    temp->data = *back;
    int index;
    index = search_num(*back,center,len);
    temp->rchild = Resume_bitree(center+index+1,back-1,len-index-1);
    temp->lchild = Resume_bitree(center,back-len+index,index);
    return temp;
}
void preorder(struct bitree *root)//前序遍历
{
    if( root != NULL)
    {
        printf("%c",root->data);
        preorder(root->lchild);
        preorder(root->rchild);
    }
}
int main(void)
{
    char *inorder  = (char *)malloc(sizeof(char [MAX]));//中序
    char *postorde = (char *)malloc(sizeof(char [MAX]));//后序
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",inorder);
        scanf("%s",postorde);
        struct bitree *root ;

        root = Resume_bitree(inorder,postorde+strlen(postorde)-1,strlen(inorder));
        preorder(root);
        printf("\n");
    }
    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])。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值