第36期:二叉树的遍历(小白必看)
时间:2022-07-25
本文章向大家介绍第36期:二叉树的遍历(小白必看),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在上一节中,我们通过例题学习了二叉树最大深度与DFS,其实就是沿着一个方向一直向下遍历。那我们可不可以按照高度一层一层的访问树中的数据呢?当然可以,就是本节中我们要讲的BFS(宽度优先搜索),同时也被称为广度优先搜索。 我们仍然通过例题进行讲解。
01、题目分析
第102题:二叉树的层次遍历 |
---|
给定一个二叉树,返回其按层次遍历的节点值。(即逐层地,从左到右访问所有节点)。 |
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其层次遍历结果:[[3],[9,20],[15,7]]
02、BFS介绍
BFS,广度/宽度优先。其实就是从上到下,先把每一层遍历完之后再遍历一下一层。假如我们的树如下:
按照BFS,访问顺序如下:
a->b->c->d->e->f->g
了解了BFS,我们开始对本题进行分析。
03、递归求解
同样,我们先考虑本题的递归解法。想到递归,我们一般先想到DFS。我们可以对该二叉树进行先序遍历(根左右的顺序),同时,记录节点所在的层次level,并且对每一层都定义一个数组,然后将访问到的节点值放入对应层的数组中。
假设给定二叉树为[3,9,20,null,null,15,7],图解如下:
根据以上分析,代码如下:
func levelOrder(root *TreeNode) [][]int {
return dfs(root, 0, [][]int{})
}
func dfs(root *TreeNode, level int, res [][]int) [][]int {
if root == nil {
return res
}
if len(res) == level {
res = append(res, []int{root.Val})
} else {
res[level] = append(res[level], root.Val)
}
res = dfs(root.Left, level+1, res)
res = dfs(root.Right, level+1, res)
return res
}
04、BFS求解
上面的解法,其实相当于是用DFS的方法实现了二叉树的BFS。那我们能不能直接使用BFS的方式进行解题呢?当然,我们可以使用Queue的数据结构。我们将root节点初始化进队列,通过消耗尾部,插入头部的方式来完成BFS。
具体步骤如下图:
根据以上分析,代码如下:
func levelOrder(root *TreeNode) [][]int {
var result [][]int
if root == nil {
return result
}
// 定义一个双向队列
queue := list.New()
// 头部插入根节点
queue.PushFront(root)
// 进行广度搜索
for queue.Len() > 0 {
var current []int
listLength := queue.Len()
for i := 0; i < listLength; i++ {
// 消耗尾部
// queue.Remove(queue.Back()).(*TreeNode):移除最后一个元素并将其转化为TreeNode类型
node := queue.Remove(queue.Back()).(*TreeNode)
current = append(current, node.Val)
if node.Left != nil {
//插入头部
queue.PushFront(node.Left)
}
if node.Right != nil {
queue.PushFront(node.Right)
}
}
result = append(result, current)
}
return result
}
- 为自定义配置的编辑提供”智能感知”的支持
- 在ASP.NET Core应用中如何设置和获取与执行环境相关的信息?
- 在ASP.NET MVC中如何应用多个相同类型的ValidationAttribute?
- [ASP.NET MVC]如何定制Numeric属性/字段验证消息
- 为.NET Core项目定义Item Template
- 晚绑定场景下对象属性赋值和取值可以不需要PropertyInfo
- 一个关于反序列化的小问题
- 两个简单的扩展方法:TrimPrefix和TrimSuffix
- 谈谈Nullable<T>的类型转换问题
- ASP.NET MVC是如何运行的(3): Controller的激活
- ASP.NET MVC是如何运行的[2]: URL路由
- 一个简单的小程序演示Unity的三种依赖注入方式
- 在Entity Framework中使用存储过程(三):逻辑删除的实现与自增长列值返回
- 在Entity Framework中使用存储过程(四):如何为Delete存储过程参数赋上Current值?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法