热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c++二叉树_大牛带你学|由二叉树的遍历序列求二叉树结构的解题方法归纳

前言二叉树章节属于数据结构考察的三大重点章节(线性表、树、图)之一,不管是在自命题院校考察和408统考都是考察频次很高的考点。今天,大牛学长就来为各位同

305852e2b05e2ee4fad1c95e4cb0f638.png

前言

二叉树章节 属于数据结构考察的三大重点章节(线性表、树、图)之一,不管是在自命题院校考察和408统考都是考察频次很高的考点。今天,大牛学长就来为各位同学总结归纳一个二叉树知识考察中的常见题型的解题方法。

在二叉树相关考察中,有这样一类题型,它形如【已知二叉树的中序遍历序列和先序遍历序列,求二叉树的后序遍历序列】同时,这类题很容易在选择题中衍生成其他题型,因此掌握它的固定解法是相当重要的。由于在解得二叉树的形态后求相关遍历序列非常简单,我们把这一类问题归结为:【由二叉树的遍历序列求二叉树结构】。

c73c5488d15898de215cb6ba6e9d27e7.png预备知识

要解决这一类问题,我们需要先回顾一下二叉树的结构以及它的四种遍历方式的特点。我们知道任何二叉树可以分为三部分:根结点(D)、左子树(L)、右子树(R)。所谓遍历二叉树,就是按某种顺序访问这三个部分。根据不同顺序可以把遍历方法分层三类:

DLR——先(根)序遍历。

LDR——中(根)序遍历。

LRD——后(根)序遍历。

同时我们也可以按层次观察:

从根结点开始遍历,按层次次序, “自上而下,从左至右”访问树中的各结点。

6df0733140e4e50e838b0cac35d4cacf.png

先序遍历ABDEC

中序遍历DBEAC

后序遍历DEBCA

层序遍历ABCDE

由此我们得到了四种遍历方式:先序遍历、中序遍历、后序遍历、层序遍历。

根据大牛学长画出的示意图,我们一起观察一下四种遍历方式的特点:

对于根结点A来说,左子树对应的是BDE这三个结点,右子树对应的是C这个结点。

• 先序遍历:DLR,以A为根结点的先序遍历序列是ABDEC,以B为根结点的先序遍历序列是BDE,以C为根结点的先序遍历序列是C。显然在先序遍历的序列当中,我们可以根据DLR划分为三个部分 (A)(BDE)(C),并且每一个部分都符合先序遍历。

• 后序遍历:LRD,以A为根结点的后序遍历序列是DEBCA,以B为根结点的后序遍历序列是DEB,以C为根结点的后序遍历序列是C。显然在后序遍历的序列当中,我们可以根据LRD划分为三个部分 (DEB)(C)(A),并且每一个部分都符合后序遍历。

• 中序遍历:LDR,以A为根结点的中序遍历序列是DBEAC,以B为根结点的中序遍历序列是DBE,以C为根结点的中序遍历序列是C。显然在中序遍历的序列当中,我们可以根据DLR划分为三个部分(DBE)(A)(C),并且每一个部分都符合中序遍历。

• 层序遍历:以A为根结点的中序遍历序列是ABCDE,以B为根结点的中序遍历序列是BDE,以C为根结点的中序遍历序列是C。层序遍历的分析比较复杂,但是我们可以根据已知的树结点的情况对遍历序列进行划分,划分为(A)(BCDE)两部分。显然层序遍历的第二部分当中左子树和右子树的结点是交替输出的,不像前三种遍历左子树和右子树独立输出,但是我们可以根据已知左子树对应的是BDE这三个结点,在遍历序列ABCDE当中选取BDE三个结点保留他们的相对位置,得到的(BDE)对应的正是左子树的层次遍历,同样的根据右子树对应的是C这个结点,在遍历序列中选取的(C)对应的正是右子树的层次遍历。

c73c5488d15898de215cb6ba6e9d27e7.png大牛总结

对于先序遍历、后序遍历以及层序遍历来说,都能够唯一地确定根结点的值!这一点异常重要!

先序遍历和层序遍历中根结点总是在序列的 第一位,

后序遍历中根结点总是在序列的 最后一位。

对于中序遍历来说,如果能够唯一地确定根结点的值,设根结点所在下标为i,那么[0...i-1]对应的就是左子树的中序遍历序列,[i+1...n]对应的就是右子树的中序遍历序列。

由此我们可以确定左子树拥有哪些结点,以及右子树拥有哪些结点。

通过遍历确定唯一的二叉树

要知道,通过遍历序列确定二叉树形态这样的操作虽然很常见,但是,存在不能确定形态的情况!

(一)单一的遍历序列不能够确定唯一一个二叉树

(二)四种遍历序列中,任意取其两种,也不一定能够确定二叉树具体确定情况如下表所示。可以看出,确定二叉树的规则可以总结为:

中序遍历是必须!其余三种取其一。

任何不满足这个口诀的序列方法都是不能唯一确定二叉树的!

fd568101e9332d2b9db4471f402c63e3.png

对于为什么不能通过先序遍历、后序遍历、层序遍历三者中的任意组合唯一确定二叉树,可以参考上面的分析过程,也可以记住一个这样的反例。这两个不相同的二叉树拥有相同的先序遍历、后序遍历、层序遍历序列。

143976fe2891ecb57a78a1e5091a7799.png

前面提到了通过先序遍历、后序遍历以及层序遍历能够唯一地确定根结点的值。当我们通过以上的三种序列之一拿到根节点值之后,观察中序遍历序列可以确定左子树和右子树拥有的结点情况。

若能确定先序遍历、后序遍历哪些结点属于左子树或右子树,对应的左子树和右子树的先序遍历、后序遍历又能唯一地确定其根结点的值。

这时候,将子树当成一棵新的树,重新去重复“找根节点、划分左右子树”的流程,直到找到所有叶子节点,二叉树的形态确定过程基本也就完成了。

c73c5488d15898de215cb6ba6e9d27e7.png常见题型

在整理好逻辑之后,大牛学长来跟大家归纳常考的题型。

具体试卷上,一般考察知道中序遍历序列,以及先后序遍历序列之一的二叉树确定问题(结点数量为n,序列下标从0开始)。根据前面的逻辑整理,这种情况的解题步骤可以归纳为:

(1)在先序遍历(后序遍历)中选择 第一个(最后一个)作为根结点T

(2)在中序遍历中寻找T,确定下标为i,则左子树为inorder[0...i-1]长度为i,右子树为inorder[i+1...n-1]长度为n-i-1

(3)在先序遍历(后序遍历)中以preorder[1...i](postorder[0...i-1])为左子树,对左子树执行(1),以preorder[i+1...n-1](postorder[i...n-2])为右子树,对右子树执行(1)

而对于已知层序遍历和中序遍历(结点数量为n,序列下标从0开始

)唯一确定二叉树基本的解题步骤为:

(1)在层序遍历中选择 第一个(最后一个)作为根结点T

(2)在中序遍历中寻找T,确定下标为i,则左子树为inorder[0...i-1]长度为i,右子树为inorder[i+1...n-1]长度为n-i-1

(3)在层序遍历中按照inorder[0...i-1]遍历整个levelorder序列确定i个结点为左子树,对左子树执行(1),按照inorder[i+1...n-1]确定n-i-1个结点为右子树,对右子树执行(1)

c73c5488d15898de215cb6ba6e9d27e7.png解题实战

题目:若某一二叉树的先序遍历序列为ABDEC,其中序遍历序列为DBEAC,求该二叉树的形态(恢复该二叉树)。

解答:

(1) 由于知道了该二叉树的先序遍历序列,可知其根节点为A。

(2) 将A拿到中序遍历序列中,可以看到A把二叉树分成了两部分,左子树DBE,右子树C。

(3) 对于整个二叉树来说,根节点A和A的唯一右子树(一个节点)C已经确定,接下来需要确定其右子树DBE(中序序列)了。

(4) A的左子树的先序遍历序列是BDE,因此很明确的知道B是左子树的根节点,也就是A的左儿子,于是把B节点拿到中序序列DBE中,看出B刚好把D、E分开,于是可以得到左子树是以B为根节点,D、E分别为左右子树的二叉树,将该二叉树放到A的左子树位置即可。最终树的形态如下图所示。

6df0733140e4e50e838b0cac35d4cacf.png

好啦,对于如何从两种二叉树遍历序列中求出二叉树形态类型题的总结和归纳就到此为止啦!希望同学们能够从中得到提升哟~

大牛学长也会不断发掘考点考题,为大家带来更加丰富有用的知识、题型总结!

今天是2020年8月14日

距离2021年考研还有 126 天  

乾坤未定,你我皆是黑马。

大牛学长一直在~

3a9b9d18a57f6c5a895feb4b29caacc8.png




推荐阅读
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有