【如何唯一确定一棵二叉树】思想分析及步骤详解

简介: 【如何唯一确定一棵二叉树】思想分析及步骤详解

一、问题引出

二叉树是一种特殊的树,它的每一个结点最多只有左右两棵子树,那么假设我们给定一个二叉树的结点值的遍历结果,如何恢复出树的结构呢?举个最简单的例子,假设给定一个二叉树的前序遍历结果为ABC,现在要根据遍历结果把二叉树恢复出来,那么能得到唯一一棵二叉树吗?显然是不行的,前序遍历是指先访问根结点,再访问左子树,最后访问右子树,那么以下五种情况都符合前序遍历结果ABC。因此,有必要探讨如何唯一确定一棵二叉树。


二、算法介绍

常用的确定一棵二叉树的算法有两种,第一种是使用两种遍历(前序+中序、后序+中序),第二种是#号法。

  • 两种遍历确定一棵二叉树:(必须要有中序遍历)
  • 前序遍历+中序遍历确定一棵二叉树;
  • 中序遍历+后序遍历确定一棵二叉树;
  • #号法确定一棵二叉树:如果没有左右子树,则使用#号代替,遍历时用#代替NULL。

下面分别对两种方法进行详细分析。

1. 中序遍历+前/后序遍历确定一棵二叉树

1.1  算法思想分析

通过上面的介绍可以看到,使用两种遍历来确定一棵二叉树的时候一定要有中序遍历。其实,这和三种遍历的自身特点是有关系的,前序遍历的顺序是先根结点,然后左子树,最后右子树,所以根结点一定在遍历结果的第一个位置上;后序遍历的顺序是,先左子树,然后右子树,最后根结点,所以根结点一定是在遍历结果的最后一个位置上。通过前序遍历和后序遍历可以确定出根结点。中序遍历的顺序是,先左子树,然后根结点,最后右子树,在遍历结果中,左右子树分别在根结点的两侧,这样就可以把左右子树区分开。可以看出,前/后序遍历和中序遍历的作用分别是:

  • 前序遍历或后序遍历用于确定根节点;
  • 中序遍历用于区分左右子树;

通过两种遍历,找出了根结点,并区分开了左右子树,这样就可以确定一棵二叉树了,下面以前序遍历加中序遍历为例,一步步分析如何通过前序遍历结果和中序遍历结果来恢复一棵二叉树(后续+中序遍历的方法与之类似,此文不再分析)。

1.2 算法流程

首先给出两个序列

前序遍历结果:A B C D E F G

中序遍历结果:C D B A F E G

第一步:确定整棵树的根结点及左右子树
  • 根据前序遍历结果确定整棵树的根结点为A ;
  • 根据根结点和中序遍历确定左右子树的结点集合,因为A是整棵树的根结点,中序遍历的顺序是先左子树,然后根结点,最后右子树。所以,在中序遍历结果中,A结点的左侧为左子树结点集合{C, D, B},A结点的右侧为右子树结点集合{F, E, G};

根据分析,可以画出分析后的结果

这样就把问题分解为{C, D, B}和{F, E, G}两个子问题,首先分析左子树

第二步:分析左子树
  • 找出{C, D, B}在前序遍历结果中对应的子序列A (B C D) E F G,将相应子序列拿出来{B C D},根据前序遍历的结果可知,B为这棵子树的根结点;
  • 找出中序遍历中该子树结点集合对应的子序列(C D B) A F E G,根据中序遍历的特点可知,{C D}为根结点B的左子树,B的右子树为空;

继续画出示意图

分析{C,D}子序列

第三步:继续分析左子树的左子树(B结点的左子树)
  • 找出{C, D}在前序遍历结果中对应的子序列A B (C D) E F G,将相应子序列拿出来{C D},根据前序遍历的结果可知,C为这棵子树的根结点;
  • 找出中序遍历中该子树结点集合对应的子序列(C D) B A F E G,根据中序遍历的特点可知,{D}在根结点C的右侧,为根结点C的右子树,C的左子树为空;

继续画出示意图

至此,整棵二叉树的左子树分析完毕,再用第二、三步同样的方法分析右子树{F,E,G}。

第四步:分析右子树
  • 找出{F,E,G}在前序遍历结果中对应的子序列A B C D (E F G),将相应子序列拿出来{F,E,G},根据前序遍历的特点可知,E为这棵子树的根结点;
  • 找出中序遍历中该子树结点集合对应的子序列C D B A (F E G),根据中序遍历的特点可知,{F}为根结点E的左子树,{G}为根结点E的右子树;

画出示意图

整棵二叉树分析完毕,并恢复出唯一的一棵二叉树,我们对该二叉树示意图进行前序遍历和中序遍历,结果分别为A B C D E F G和C D B A F E G,与题目中给的前序遍历序列和中序遍历序列一致,证明我们恢复得到树是正确的。

2. 号法确定一棵二叉树

2.1 算法思想分析

#号法确定一棵树的思想是,如果一个结点没有左右子树,也就是说如果左子树或右子树为NULL,就用一个#号代替,在遍历时给出带有#的遍历结果,既然没有左右子树就用一个#代替,那么连续两个#号前的结点一定是叶子结点,也就能确定一棵子树的结束,这样通过一种遍历的结点序列就能唯一确定一棵二叉树。

2.2 算法流程

首先给出一个#号法前序遍历的结点序列

前序遍历:ABC#D###EF##G##

具体步骤:
  1. 找出后面有连续两个#的结点,D F G这三个结点就是叶子结点;
  2. 根据前序遍历可知,A是整棵树的根结点;
  3. 第一个出现连续两个#的位置为D,所以D结点应该是整棵树的左子树的结束,那么左右子树就区分开了,{B C D}为左子树,{E F G}为右子树;
  4. 分析左子树{B C D}的根结点以及左子树的左右子树。先分理出左子树序列BC#D###,因为是前序遍历,B为左子树的根结点,第一个连续两个#的位置是D,所以D结点是以B为根结点的树的左子树的结束,那么剩下的一个#就是B结点的右子树。因此,B结点的左子树集合为C#D##,B结点的右子树为#;
  5. 分析子树{C#D##},由前序遍历特点可知,C为根结点,D为子树终点,因为D前面有一个#可知,C的左子树为#,右子树为D;
  6. 分析A的右子树{EF##G##},E为根结点,F为左子树,G为右子树;

三、结论

唯一确定一棵树的关键就在于寻找根结点和划分左右子树,不管是前序加中序遍历的方法还是#号法前序遍历的方法,都是在寻找根节点,划分左右子树的一个过程。


相关文章
|
6月前
|
存储 算法 Java
Java中,树与图的算法涉及二叉树的前序、中序、后序遍历以及DFS和BFS搜索。
【6月更文挑战第21天】Java中,树与图的算法涉及二叉树的前序、中序、后序遍历以及DFS和BFS搜索。二叉树遍历通过访问根、左、右子节点实现。DFS采用递归遍历图的节点,而BFS利用队列按层次访问。以下是简化的代码片段:[Java代码略]
51 4
|
2月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
32 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
6月前
|
算法
数据结构和算法学习记录——初识二叉树(定义、五种基本形态、几种特殊的二叉树、二叉树的重要性质、初识基本操作函数)
数据结构和算法学习记录——初识二叉树(定义、五种基本形态、几种特殊的二叉树、二叉树的重要性质、初识基本操作函数)
70 0
|
7月前
|
存储 算法 搜索推荐
深度优先遍历与广度优先遍历:理解它们的原理与差异
深度优先遍历与广度优先遍历:理解它们的原理与差异
|
算法
广度优先遍历(BFS):逐层探索图的算法奥秘
在图论中,广度优先遍历(Breadth-First Search,BFS)是一种图遍历算法,它以一种逐层的方式探索图的节点。通过从起始节点开始,逐层向外扩展,BFS能够帮助我们解决许多与图相关的问题。
135 0
【Leetcode -100.相同的树 -104.二叉树的深度】
【Leetcode -100.相同的树 -104.二叉树的深度】
41 0
|
C语言 C++
【哈夫曼树】基本概念、构建过程及C++代码
【哈夫曼树】基本概念、构建过程及C++代码
291 0
|
存储
树和二叉树的基本概念和性质
树和二叉树的基本概念和性质
|
算法
算法系列-二叉树构建
在内卷潮流的席卷下,身为算法小白的我不得不问自己,是否得踏上征程,征服这座巍巍高山。 从零开始,终点不知何方,取决于自己可以坚持多久。 希望你可以和我一样,克服恐惧,哪怕毫无基础,哪怕天生愚钝,依然选择直面困难。
|
存储
树和二叉树的基本概念
1.树的概念: a.树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。 b.把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 c.有一个特殊的结点,称为根结点,根节点没有前驱结点 除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集 合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以 有0个或多个后继 因此,树是递归定义的。 .
93 0
树和二叉树的基本概念

热门文章

最新文章