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

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

一、问题引出

二叉树是一种特殊的树,它的每一个结点最多只有左右两棵子树,那么假设我们给定一个二叉树的结点值的遍历结果,如何恢复出树的结构呢?举个最简单的例子,假设给定一个二叉树的前序遍历结果为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为右子树;

三、结论

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


相关文章
|
3天前
|
算法
二叉树遍历:探索树结构的关键步骤
【10月更文挑战第29天】
9 1
|
5月前
|
算法
数据结构和算法学习记录——初识二叉树(定义、五种基本形态、几种特殊的二叉树、二叉树的重要性质、初识基本操作函数)
数据结构和算法学习记录——初识二叉树(定义、五种基本形态、几种特殊的二叉树、二叉树的重要性质、初识基本操作函数)
48 0
|
6月前
|
存储 算法 搜索推荐
深度优先遍历与广度优先遍历:理解它们的原理与差异
深度优先遍历与广度优先遍历:理解它们的原理与差异
|
6月前
|
算法
平衡二叉树的构建(递归
平衡二叉树的构建(递归
91 0
|
存储 算法
树和二叉树基础概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
|
C语言 C++
【哈夫曼树】基本概念、构建过程及C++代码
【哈夫曼树】基本概念、构建过程及C++代码
249 0
|
存储
树和二叉树的基本概念和性质
树和二叉树的基本概念和性质
【树与二叉树】二叉树链式结构及实现--万字详解介绍(上)
【树与二叉树】二叉树链式结构及实现--万字详解介绍(上)
|
存储 安全 C++
【树与二叉树】二叉树链式结构及实现--万字详解介绍(下)
【树与二叉树】二叉树链式结构及实现--万字详解介绍(下)
|
存储 算法
二叉树全分析(超详细总结建议收藏)
二叉树全分析(超详细总结建议收藏)
213 0