题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
输入:
输入可能包含多个测试样例,对于每个测试案例,
输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。
输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。
输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。
输出:
对应每个测试案例,输出一行:
如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。
如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。
样例输入:
81 2 4 7 3 5 6 84 7 2 1 5 3 8 681 2 4 7 3 5 6 84 1 2 7 5 3 8 6
样例输出:
7 4 2 5 8 6 3 1 No
采用递归的方式重构二叉树,关键是要考虑到一些特殊情况,比如:只有根节点的二叉树、只有左子树或只有右子树的二叉树以及二叉树根节点为NULL、前序中序序列不匹配导致不能重构二叉树等。
AC代码如下(一直在如何实现判断能否重构二叉树的地方徘徊,在九度论坛里大致看了下,借鉴了下各位前辈的思路:定义一个全局bool变量,用来跟踪判断能够重构):
#include<stdio.h>
#include<stdlib.h>
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
BinaryTreeNode * ConstructCore(int*,int*,int*,int *);
bool canRebuild;//用来标识是否能重构二叉树
/*
preorder为前序遍历数组,inorder为中序遍历数组,length为数组长度
*/
BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
if(preorder==NULL||inorder==NULL||length<=0)
{
canRebuild=false;
return NULL;
}
int i;
for(i=0;i<length;i++)
if(preorder[0] == inorder[i])
break;
//如果遍历inv结束都没有找到与pre[0]相等的值,则不能重构二叉树
if(i >= length)
{
canRebuild = false;
return NULL;
}
return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}
BinaryTreeNode* ConstructCore(int* startPreorder,int* endPreorder,int* startInorder,int* endInorder)
{
//前序遍历序列的第一个数字是根节点的值
int rootValue=startPreorder[0];
BinaryTreeNode* root = new BinaryTreeNode();
root->m_nValue=rootValue;
root->m_pLeft=root->m_pRight=NULL;
if(startPreorder==endPreorder)
{
if(startInorder==endInorder&&*startPreorder==*startInorder)
return root;
else
return NULL;
}
//在中序遍历找到根节点的值
int* rootInorder=startInorder;
while(rootInorder<=endInorder&&*rootInorder!=rootValue)
++rootInorder;
if(rootInorder==endInorder&&*rootInorder!=rootValue)
return NULL;
int leftLength=rootInorder-startInorder;
int* leftPreorderEnd = startPreorder+leftLength;
if(leftLength>0)
{
// 构建左子树
root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,
startInorder,rootInorder-1);
}
if(leftLength<endPreorder-startPreorder)
{
//构建右子树
root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,
rootInorder+1,endInorder);
}
return root;
}
void BehTraverse(BinaryTreeNode* pTree)
{
if(pTree != NULL)
{
if(pTree->m_pLeft!= NULL)
BehTraverse(pTree->m_pLeft);
if(pTree->m_pRight != NULL)
BehTraverse(pTree->m_pRight);
printf("%d ",pTree->m_nValue);
}
}
void DestroyTree(BinaryTreeNode* pTree)
{
if(pTree)
{
if(pTree->m_pLeft)
DestroyTree(pTree->m_pLeft);
if(pTree->m_pRight)
DestroyTree(pTree->m_pRight);
free(pTree);
pTree = NULL;
}
}
int main()
{
int length;
BinaryTreeNode* pTree=NULL;
while(scanf("%d",&length)!=EOF)
{
int* preorder = (int*)malloc(length*sizeof(int));
int* inorder = (int*)malloc(length*sizeof(int));
int i;
for(i=0;i<length;i++)
scanf("%d",preorder+i);
for(i=0;i<length;i++)
scanf("%d",inorder+i);
canRebuild = true;
BinaryTreeNode* root = Construct(preorder,inorder,length);
printf("%d\t",root->m_nValue);
}
}
结果:
分享到:
相关推荐
在IT领域,特别是数据结构和算法的学习中,构建和重构二叉树是一项基本技能。本文将深入探讨如何根据前序序列和中序序列构建二叉树,并使用MFC(Microsoft Foundation Classes)框架来实现图形化输出。对于二叉树的...
在本压缩包“cd.zip_THU OJ_oj_reconfiguration_thu dsa_重构 二叉树”中,主要涉及的是清华大学(THU)在线判题系统(Online Judge,简称OJ)上的一个编程挑战,具体是关于二叉树的重构问题。这个任务涉及到的数据...
分析写一个简单但不失一般性的例子进行分析:返回二叉树:一步递归:前序序列的第一个元素为当前根结点,create根结点。返回值:本级递归创建根结点后,左右孩子指针
二叉树的重建是指根据给定的前序遍历和中序遍历序列重构出原来的二叉树结构。这一过程依赖于二叉树的性质:前序遍历的第一个元素是根节点,中序遍历中根节点左侧的元素构成左子树,右侧的元素构成右子树。通过递归地...
真二叉树重构
3. 给定二叉树的先序和中序遍历结果,如何重构二叉树。 ### 1. 利用先序遍历和层次遍历的结果建立二叉树 在C++中,我们可以定义一个`BinTreeNode`类来表示二叉树中的每个节点,并且定义一个`BinaryTree`类来封装...
此外,还需分析树的遍历结果,并设计算法实现先序和中序遍历(或中序和后序遍历),以重构二叉树。 实验代码包含两个部分。首先,定义了一个`btnode`结构体,其中包含元素数据、左子节点指针和右子节点指针。接着,...
这通常通过递归地遍历树并生成表示树结构的字符串,然后写入文件,或者读取文件内容并重构二叉树实现。 总之,二叉查找树是Java中实现高效数据管理的重要工具。通过理解其基本操作,如创建、插入、查找和删除,以及...
在探讨中,还涉及了如何根据遍历结果重构二叉树的方法,不仅提供了解题思路,还强调了实际操作中的关键步骤和注意事项。 总体来说,本文对二叉树的基本概念、存储方式和遍历方法进行了全面的介绍,并通过实际操作中...
4. 给定二叉树的后序遍历和中序遍历序列,可以利用这些信息重构二叉树并求出前序遍历序列。 5. 通过后序遍历序列和中序遍历序列可以构建出二叉树,然后进行前序遍历以得到前序遍历序列。 理解并掌握这些知识点对于...
类似地,如果给定后序和中序遍历的结果,也可以重构二叉树。在后序遍历中,最后一个元素是根节点,因为它是所有子节点之后访问的。中序遍历仍然可以帮助我们区分左右子树,但是这次我们需要找到根节点右侧的子序列来...
每个题目对应的文档(如`重构二叉树.doc`、`括号编码.doc`等)都提供了详细的题目描述和可能的解答思路。通过实践这些题目,学习者可以深化对C/C++编程语言的理解,提升算法设计和问题解决能力。
之前发布的单独c文件,太大,不可重用,所以我把它重构了,打散成.h和.c文件,加入了Makefile进行编译。 用tar命令解压后,就可以make 运行了。详情请看readme,之前发布的单独文件也在里面
对于A卷的第1题,要求考生编写一个C程序,能够根据给定的二叉树中序和后序遍历序列来重构二叉树,并输出前序遍历序列以及度为0的节点(即叶子节点)的个数。这个题目主要考察了二叉树的遍历和构建方法。首先,中序...
根据给定的遍历序列,我们可以重构二叉树。例如,给定的前序遍历和中序遍历序列可以画出特定的二叉树结构。 5. **图的遍历**:图的深度优先遍历(DFS)和广度优先遍历(BFS)是两种重要的遍历方法。DFS通常从一个...
3. 重构二叉树:当达到一定的重构条件(如符号出现次数或时间间隔)时,基于当前权重重新构造二叉树。 4. 生成码字:使用新树结构为每个符号生成码字。 5. 输出编码结果:将生成的码字输出,形成压缩后的数据流。 `...
根据给定的遍历序列,我们可以重构二叉树的形态。 算法是解决问题的精确步骤描述,具有可行性、确定性、有穷性和拥有足够的情报等特性。算法的时间复杂度和空间复杂度分别描述了算法运行所需的计算时间和内存空间。...
根据两种遍历序列可以重构二叉树。 第三部分介绍了图的存储方法,包括邻接矩阵和邻接表,以及十字链表。图的遍历包括深度优先搜索和广度优先搜索,生成树和最小生成树是图的基本操作。拓扑排序需要无环的有向图,...
根据这两个序列,我们可以重构二叉树的先序序列(preorder traversal),即从根节点开始,然后遍历左子树,最后遍历右子树。正确答案是 B:E、A、C、B、D、G、F。这道题考察了二叉树的三种遍历方法的理解和应用。 ...
14. 给定后序和中序遍历,可以重构二叉树,这里先序遍历是`cedba`。 15. 在线索二叉树中,结点是叶子结点当且仅当左右线索都为1。 16. 二叉树的性质表明,度为1的结点3个,度为2的结点4个,叶子结点数为5。 17. 权值...