二叉树遍历相关题目¶
约 2628 个字 570 行代码 16 张图片 预计阅读时间 16 分钟
本篇介绍¶
二叉树主要考察的还是根据具体的遍历方式实现问题,所以在完成后面的题目之前先熟悉二叉树的遍历方式是非常重要的,与数据结构:二叉树(基础)篇不同,本次除了会包含递归解法外,还会包含迭代法
二叉树的遍历主要分为深度优先搜索和广度优先搜索,深度优先一般就是前中后序三个遍历方式,深度优先就是层序遍历,在下面的题目中,也主要考察这两种遍历方式
二叉树的深度优先搜索¶
力扣144.二叉树的前序遍历¶
问题描述:
Quote
给你二叉树的根节点root
,返回它节点值的前序遍历。
示例 1:
C++ | |
---|---|
1 2 |
|
解释:
示例 2:
C++ | |
---|---|
1 2 |
|
解释:
示例 3:
C++ | |
---|---|
1 2 |
|
示例 4:
C++ | |
---|---|
1 2 |
|
思路分析:
-
解法1:递归
二叉树的前序遍历在数据结构:二叉树(基础)部分已经提过基本的递归思路,本题最简单的思路也就是递归写法,此处不再赘述
-
解法2:迭代
二叉树前序遍历的迭代写法的主要思路就是用栈模拟递归的过程,因为前序遍历的顺序是:中左右,所以根节点是第一个被处理的节点,此时栈内的数据就是当前子树的根节点。如果栈不为空说明还没有走完整棵二叉树,否则每一次遍历时,先取出当前栈顶的元素,该元素就是当前子树的根节点,取出后弹出当前元素,接着走向右子树,注意不是左子树,因为栈是先进后出,而下一次是左子树先被去除,所以右子树先进才能保证左子树在栈顶
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
力扣94.二叉树的中序遍历¶
问题描述:
Quote
给定一个二叉树的根节点root
,返回它的中序遍历。
示例 1:
C++ | |
---|---|
1 2 |
|
示例 2:
C++ | |
---|---|
1 2 |
|
示例 3:
C++ | |
---|---|
1 2 |
|
思路分析:
-
解法1:递归
二叉树的中序遍历在数据结构:二叉树(基础)部分已经提过基本的递归思路,本题最简单的思路也就是递归写法,此处不再赘述
-
解法2:迭代
二叉树中序遍历的迭代写法相对比较简单,先找到左子树,再取出当前节点,当取出左节点后,下一个节点一定是根节点,所以只需要将
root
更新为nullptr
就可以防止重复走到原来的节点。考虑到如果左节点是叶子,那么此时root->right
一定为nullptr
,所以可以更新为root = root->right
,如果存在右节点,则下一次又会走右侧子树重复前面的步骤。如果不存在右节点,则下一次取出的就是根节点
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
力扣145.二叉树的后序遍历¶
问题描述:
Quote
给你一棵二叉树的根节点root
,返回其节点值的后序遍历。
示例 1:
C++ | |
---|---|
1 2 3 |
|
解释:
示例 2:
C++ | |
---|---|
1 2 3 |
|
解释:
示例 3:
C++ | |
---|---|
1 2 3 |
|
示例 4:
C++ | |
---|---|
1 2 3 |
|
思路分析:
-
解法1:递归
二叉树的后序遍历在数据结构:二叉树(基础)部分已经提过基本的递归思路,本题最简单的思路也就是递归写法,此处不再赘述
-
解法2:迭代
二叉树后序遍历的迭代写法有两种,一种是变向的前序遍历,另外一种就是常规意义上的后序遍历
对于变向的前序遍历,其实就是根据后序遍历的顺序「中右左」的前序遍历的反向「左右中」,所以只需要将前序遍历的「中左右」改为「中右左」,再反向结果集即可。但是注意,这个方法只是完成了遍历的结果,遍历的方法基本上是不太严谨的,或者说是异构的前序遍历(即利用了两次反转:先反转为中右左,再反转结果集)
常规意义上的后序遍历就是按照「左右中」的顺序进行,基本思路和中序遍历很类似,先一直走左子树,直到找到最左节点,这个过程中也要记录遍历过的节点。接着获取到当前节点,与中序不同的是,此时需要判断是否存在右孩子,因为后序遍历处理中间节点的逻辑是在遍历完右子树之后,如果右子树存在,那么还需要继续遍历,即将右子树节点压栈,否则当前节点就是当前子树的最后一个节点
关键步骤:
后序遍历的常规迭代法需要注意,要使用到一个变量prev
表示前一个节点,如果当前节点的右孩子等于prev
,说明当前子树的右子树遍历完毕,当前及诶点就是当前子树的根节点,并且还需要在插入节点到结果集之后将root
置为空,防止多次走向同一棵左子树
例如下面的例子中,prev
当前指向的是7节点:
下一次循环中,首先会从栈内取出元素,当前栈顶元素为5,所以当前节点就是5,如果没有判断5的右子树是否等于prev
,那么就会出现再一次走到右子树将5再次插入到栈内并再次走向同一棵右子树的情况
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
二叉树的广度优先搜索¶
力扣102.二叉树的层序遍历¶
问题描述:
Quote
给你二叉树的根节点root
,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。
示例 1:
C++ | |
---|---|
1 2 |
|
示例 2:
C++ | |
---|---|
1 2 |
|
示例 3:
C++ | |
---|---|
1 2 |
|
思路分析:
二叉树的层序遍历就是利用队列,基本思路已经在数据结构:二叉树(基础)中提及,此处不再赘述,但是本题除了实现层序遍历二叉树外,还需要确定每一个节点所在的层,此时就需要使用到计数器,计数器由队列的大小进行初始化,起始是计数器为1,代表第一层只有一个节点,以此类推
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
根据上面的层序遍历,可以完成下面类似的题目:
Info
下面的题目是部分与层序遍历相关的题目,后面也会有其他题目会使用到层序遍历的思路,代码也可能基本类似
力扣107.二叉树的层序遍历Ⅱ¶
问题描述:
Quote
给你二叉树的根节点root
,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
示例 1:
C++ | |
---|---|
1 2 |
|
示例 2:
C++ | |
---|---|
1 2 |
|
示例 3:
C++ | |
---|---|
1 2 |
|
思路分析:
本题就是将正常层序遍历的结果集反转即可
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
力扣199.二叉树的右视图¶
问题描述:
Quote
给定一个二叉树的根节点root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值
示例 1:
C++ | |
---|---|
1 2 |
|
解释:
示例 2:
输入:root = [1,2,3,4,null,null,null,5]
输出:[1,3,4,5]
解释:
示例 3:
C++ | |
---|---|
1 2 |
|
示例 4:
C++ | |
---|---|
1 2 |
|
思路分析:
所谓右视图,就是只看得到最右侧的节点,所以从层序遍历的角度来看,只需要取出每一层的最后一个节点即可
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
力扣637.二叉树的层平均值¶
问题描述:
Quote
给定一个非空二叉树的根节点root
, 以数组的形式返回每一层节点的平均值。与实际答案相差\(10^{-5}\)以内的答案可以被接受。
示例 1:
C++ | |
---|---|
1 2 3 4 |
|
示例 2:
C++ | |
---|---|
1 2 |
|
思路分析:
只需要在层序遍历中计算总和,最后在进入下一层之前计算当前层的平均值即可
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
力扣429.N叉树的层序遍历¶
问题描述:
Quote
给定一个N叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由null
值分隔(参见示例)。
示例 1:
C++ | |
---|---|
1 2 |
|
示例 2:
C++ | |
---|---|
1 2 |
|
思路分析:
基本思路还是层序遍历,但是注意,每一个孩子都存储在vector中,所以需要遍历vector将节点插入到队列
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
力扣515.在每个树行中找最大值¶
问题描述:
Quote
给定一棵二叉树的根节点root
,请找出该二叉树中每一层的最大值。
示例1:
C++ | |
---|---|
1 2 |
|
示例2:
C++ | |
---|---|
1 2 |
|
思路分析:
使用层序遍历,在每一层中找出最大值即可
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
力扣116.填充每个节点的下一个右侧节点指针¶
问题描述:
Quote
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
C++ | |
---|---|
1 2 3 4 5 6 |
|
填充它的每个next
指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将next
指针设置为NULL
。
初始状态下,所有next
指针都被设置为NULL
。
示例 1:
C++ | |
---|---|
1 2 3 |
|
示例 2:
C++ | |
---|---|
1 2 |
|
思路分析:
使用层序遍历,将每一层的节点直接相连,除了每一层的最后一个节点需要指向空
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
力扣117.填充每个节点的下一个右侧节点指针Ⅱ¶
类似力扣116.力扣117填充每个节点的下一个右侧节点指针Ⅱ
本题和116题不一样的是,本题是普通的二叉树,但是使用层序遍历不需要考虑这个问题,所以可以直接使用116题的代码:
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|