educoder数据结构 树 第1关:由双遍历序列构造二叉树

educoder数据结构 树 第1关:由双遍历序列构造二叉树

这是题目

本关任务:实现 ConstructTree.cpp 里的TNode* InPreToTree(char *pa, char *ia, int p1, int p2, int i1, int i2)函数。

相关知识
给定一棵二叉树的前序遍历序列和中序遍历序列可以构造出这棵二叉树。例如前序序列是ABDECFG,中序序列是DBEAFCG,那么这颗二叉树的结构如图 1 所示。

树结点结构定义为:

struct TNode{
char data;
struct TNode* left;
struct TNode* right;
};
编程要求
本关任务是实现 ConstructTree.cpp 里的TNode* InPreToTree(char *pa, char *ia, int p1, int p2, int i1, int i2)函数。

该函数的功能是由前序遍历序列和中序遍历序列构造二叉树。前序序列为pa[p1:p2],中序序列为ia[i1:i2],返回所构造的二叉树的根指针。

提示1:这是一个递归函数,在主程序中调用:
InPreToTree(pa,ia,0,n-1,0,n-1),其中n是序列长度。
提示2:由于在DeleteTree()中是使用delete删除一个树结点,所以在InPreToTree()需要使用new来申请结点空间。

//ConstructTree.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ConstructTree.h"
/*
InPreToTree(): 由前序遍历序列和中序遍历序列构造二叉树
前序序列为pa[p1:p2]
中序序列为ia[i1:i2]
返回所构造的二叉树的根指针
*/
TNode* InPreToTree(char *pa, char *ia, int p1, int p2, int i1, int i2)
{
    //在begin和end之间添加你的代码
    /********* begin **********/
    /********* end ************/
}
void PrintPostTravel(TNode* t)
{
    if(t==NULL) return;
    if(t->left) PrintPostTravel(t->left);
    if(t->right) PrintPostTravel(t->right);
    printf("%c", t->data);
}
void DeleteTree(TNode* t)
{
    if(t==NULL) return;
    if(t->left) DeleteTree(t->left);
    if(t->right) DeleteTree(t->right);
    delete t;
}

测试说明
本关的测试过程如下:

平台编译 step1/Main.cpp ;
平台运行该可执行文件,并以标准输入方式提供测试输入;
平台获取该可执行文件的输出,然后将其与预期输出对比,如果一致则测试通过;否则测试失败。
输入格式:
输入前序序列
输入中序序列

输出格式:
输出后序序列

以下是平台对 step1/Main.cpp 的测试样例:

样例输入
ABDECFG
DBEAFCG

样例输出
Post Travel Result:DEBFGCA

我的code

/*
InPreToTree(): 由前序遍历序列和中序遍历序列构造二叉树
前序序列为pa[p1:p2]
中序序列为ia[i1:i2]
返回所构造的二叉树的根指针
*/
TNode* InPreToTree(char *pa, char *ia, int p1, int p2, int i1, int i2)
{
   
   
   /*请在BEGIN和END之间实现你的代码*/
   /*****BEGIN*****/
   //递归终止条件,下标范围出界
   if(p2-p1<0){
       return NULL;
   }
   if(i2-i1<0){
       return NULL;
   }
   
   char curRoot=*pa;
   int i=0;
   //左子树有i个节点
   while(*(ia+i)!=curRoot){
       i++;
   }
   //左子树的中序遍历序列,下标范围是(i1,i1+i-1)
   char *leftIa=ia;
   //左子树的前序遍历序列,下标范围是(p1+1,p1+i)
   char *leftPa=pa+1;
   //右子树的中序遍历序列,下标范围是(i1+i+1,i2)
   char *rightIa=ia+i1+i+1;
   //右子树的前序遍历序列,下标范围是(p1+i+1,p2)
   char *rightPa=pa+p1+i+1;

   TNode *curNode = new TNode;
   curNode->left = InPreToTree(leftPa,leftIa,0,i-1,0,i-1);
   curNode->data = curRoot;
   curNode->right = InPreToTree(rightPa,rightIa,0,p2-p1-i-1,0,i2-i1-i-1);

   return curNode;
   
   /******END******/
   /*请不要修改[BEGIN,END]区域外的代码*/
} 

### 回答1: 遍历序列是指前序遍历序列和中序遍历序列或者后序遍历序列和中序遍历序列。通过这两个序列可以构造出一棵二叉树。 具体的构造方法如下: 1. 从前序遍历序列中取出根节点,然后在中序遍历序列中找到根节点的位置,将中序遍历序列分成左子和右子两部分。 2. 根据左子和右子的长度,将前序遍历序列和中序遍历序列分成左子和右子两部分。 3. 递归地构造左子和右子,直到序列为空或者只有一个节点。 4. 返回根节点,将左子和右子挂在根节点下面。 例如,给定前序遍历序列[1,2,4,5,3,6,7]和中序遍历序列[4,2,5,1,6,3,7],可以构造出如下的二叉树: ``` 1 / \ 2 3 / \ / \ 4 5 6 7 ``` 需要注意的是,如果给定的序列不是一棵合法的二叉树遍历序列,那么就无法构造出一棵二叉树。 ### 回答2: educoder遍历序列构造二叉树是一种常用的二叉树生成方法。遍历序列是指前序遍历序列和中序遍历序列,通过这两个序列可以唯一的构建出一个二叉树。 首先,我们需要了解前序遍历和中序遍历的概念。前序遍历的顺序是:根节点、左子、右子;中序遍历的顺序是:左子、根节点、右子。在前序遍历中,第一个节点是根节点,在中序遍历中,根节点是位于中间的节点。当我们通过前序遍历和中序遍历获得了根节点的值之后,我们就可以确定左子和右子的范围。 例如,如果我们有前序遍历序列[1,2,4,5,3,6,7]和中序遍历序列[4,2,5,1,6,3,7]。我们首先从前序遍历序列中获取根节点的值1,而在中序遍历序列中,值1在序列的第4个位置,这意味着值1是这个二叉树的根节点。接下来,我们可以根据根节点的位置,将中序遍历序列分为两部分:左子[4,2,5]和右子[6,3,7]。同样,我们也可以根据这个划分,将前序遍历序列中的节点分为左子[2,4,5]和右子[3,6,7]。这样,我们就可以得到左子的前序遍历序列[2,4,5]和中序遍历序列[4,2,5],再以同样的方式处理右子。 接着,我们可以递归的进行这个过程,不断的分割左右子,直到将所有的节点都处理完毕。最后,我们就可以得到一棵二叉树。总的来说,educoder遍历序列构造二叉树是一种简单、方便的构建二叉树的方法,它的实现比较容易理解,适合初学者掌握。 ### 回答3: educoder是一个在线编程学习平台,他提供了丰富的题目和实践场景,能够帮助学生深入理解编程核心知识和应用技术,其中既有基础课程,也有高级课程。其中,educoder提供了一道非常经典的编程题目:由遍历序列构造二叉树遍历序列是指二叉树的一个前序遍历序列和中序遍历序列或后序遍历序列和中序遍历序列。而根据这两个序列,我们就能够恢复出原来的二叉树。 具体实现方式如下:先根据前序遍历序列找到根节点,然后找到中序遍历序列中根节点所在的位置,并分别递归构造左子和右子。具体而言,先跳过根节点,将前序遍历序列分成左子和右子两部分,同样的,将中序遍历序列分成左子和右子两部分。然后再递归调用构造函数,一边处理左子,一边处理右子,最终构造出完整的二叉树。 由于这种算法是递归实现,因此时间复杂度为O(n),其中n为二叉树的节点数。由于educoder提供的程序模板已经实现了大部分代码,只需要实现一小段构造函数即可,因此这道题目适合初学者练习。 总之,由遍历序列构造二叉树是一道非常经典的编程题目,对于学习二叉树的同学而言,这是一个难得的练习机会。通过这道题目的实践,同学们能够更深入地理解二叉树遍历算法和递归实现方式,从而更好地掌握二叉树知识。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值