广度优先搜索(1)之树的层序遍历

2023-11-03

零、导言

这一系列博客的创作初衷是为了记录自己在刷题过程中对于一些比较经典的并且很哇塞的题型的所思所想,巩固所学,即时复盘。 正因为是为了便于自己复盘,所以大多是以自己的思维模式书写。如果小伙伴们在阅读的时候发现什么错误、对内容有疑问以及对书写排版等有改进意见的话,请评论区留言指正!

一、例子引入

1、题目描述

剑指 Offer 32 - I. 从上到下打印二叉树

  从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
输入:
在这里插入图片描述
返回:
[3,9,20,15,7] \texttt{[3,9,20,15,7]} [3,9,20,15,7]

2、题目分析

  (1)题目中要求的“从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印”,也就是层序遍历的内容。有别于树的遍历中的 前序、中序以及后续遍历中使用的深度优先搜索,这里实现树的层序遍历利用的是 广度优先搜索
  (2)实现树的层序遍历具体的做法是维护一个队列 q 和一个答案容器 ret :队列用来存放树的节点,答案容器用来存放最终的输出答案。完成好准备工作之后,进行如下操作:

  • 首先把根节点存入队列 q
  • 队列只要不为空就一直循环读取队列中的队首元素:
      当前读取的队首元素存入 ret ,当当前读取的队首元素还有子节点的话依次把左子节点、右子节点存入队列;

  (3)可能会有读者有这样的疑问,对于二叉树我们知道有左子树和右子树,如果是 N叉树 的情况,如何知道该树有几个子节点呢?这个就要看树的结构了,一般在答题区域都会有已经实现了的结构体或类了。可以参照 LeetCode 429. N 叉树的层序遍历 中答题区域的 N叉树 数据结构的实现。

3、算法实现与解释

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> levelOrder(TreeNode* root) {
        if(root == NULL){
            return {};
        }
        vector<int> ret;
        queue<TreeNode*> Q;			
        Q.push(root);						// push根节点

        while(!Q.empty()){					// 循环的条件
            TreeNode* now = Q.front();		// 读取队首元素
            ret.push_back(now->val);		// push进答案容器
            Q.pop();

            if(now->left){					// 判断是否有左子节点
                Q.push(now->left);
            }
            if(now->right){					// 判断是否有右子节点
                Q.push(now->right);			
            }
        }
        
        return ret;
    }
};

二、概念定义

例子看完了,相信大家对这个题目以及 广度优先搜索——层序遍历 已经有了初步的认识了。现在我们来详细解读一下广度优先搜索和层序遍历。

1、定义

维基百科 广度优先搜索算法 (英语:Breadth-First Search,缩写为BFS),又译作 宽度优先搜索 ,或 横向优先搜索 ,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。广度优先搜索的实现一般采用open-closed表。

在下图所示的广度优先搜索的示例图中:坐标(1,2)处有一个“小人”,可以向左、右、上、下四个方向移动,每次移动仅可以沿着一个方向移动一格。每一个方格内都一个数字,表示“小人”行走到该方格内所需的行动步数。数值相同的方格表示这些方格处于同一层中。通过某一方格向外扩散实现“小人”行走到任意方格的目的。该图是一个典型的广度优先搜索的例子。

广度优先搜索示意图

层序遍历: 是树众多遍历算法中的一种,树的遍历方法有前序遍历、中序遍历、后续遍历和层序遍历等等。
以上提及的遍历方法的定义以及求解方法见下表所示:

项目 含义(以二叉树为例) 方法
层序遍历 按层对树进行遍历,每一层从左往右依次遍历 BFS
前序遍历 按照先跟节点再左子节点,最后再遍历右子节点的顺序对一棵树进行遍历 DFS
中序遍历 按照先左子节点再根节点,最后再遍历右子节点的顺序对一棵树进行遍历 DFS
后续遍历 按照先左子节点再右子节点,最后再遍历根节点的顺序对一棵树进行遍历 DFS

2、深入理解

通过做一些广搜类和深搜类的算法题目,我们可以发现:

  • 对于深搜类的题目会用到 这种数据结构(有些题目会使用 vector<> 容器来代替);
  • 对于广搜类的题目,我们会使用到 queue<> 队列 这种数据结构,有时候也会使用 priority_queue<> 优先队列 这种数据结构

那为什么会是这样呢?
还是要从定义出发,以树结构为例:

  • 深搜要一头扎到底,从树的根节点一直扎到叶子节点,然后再慢慢的回溯,这就会涉及到 后入先出 的问题,具体的在 深度优先搜索 的章节再细讲。
  • 广度优先搜索,广搜从树的根节点开始,沿着树的宽度方向开始搜索,依次加入当前层的各个子节点,然后再依次读取各个子节点的子节点。直到队列为空,结束循环。
    以例子中的二叉树为例:
    入队出队模拟

3、相关知识

通过以上的分析,可以发现熟知 队列 的相关操作是十分必要的。
参照 四、总结(4)回顾队列知识。

三、相关习题

题号 难度
剑指 Offer 32 - I. 从上到下打印二叉树 中等
剑指 Offer 32 - II. 从上到下打印二叉树 II 简单
剑指 Offer 32 - III. 从上到下打印二叉树 III 中等
429. N 叉树的层序遍历 中等
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

广度优先搜索(1)之树的层序遍历 的相关文章

  • Python做简单小项目,Python如何赚钱项目

    Python都可以做哪些副业 1 兼职处理数据Excel整理数据功能虽然很强大 但在Python面前 曾经统治职场的它也的败下阵来 因为Python在搜集数据整理分析数据的过程中更加便捷 通过几行代码还可以实现自动化操作 如果你学会Pyth

随机推荐

  • 将输入的一行字符中的大写字符改为小写字符。(C语言)

    代码 include
  • 基于javaweb的留学生信息交流论坛

    该在线留学生交流网站 是一款主要以留学生交流为主题的交流性质的论坛网站 采用了SSH框架技术开发 利用mysql作为数据库 主要展示了留学新闻和论坛交流的功能 方便了交流和对澳洲那边生活的了解 面对面和去过的人交流 系统是一款简单毕业设计学
  • Linux中ELF格式文件介绍

    ELF Executable and Linkable Format 即可执行连接文件格式 是一种比较复杂的文件格式 但其应用广泛 与linux下的其他可执行文件 a out cof 相比 它对节的定义和gnu工具链对它的支持使它十分灵活
  • 最近忙了些啥

    最近自己忙忙叨叨 忙忙叨叨的 不知道都干了些啥 一直在围绕网站SNS建设的规划 讨论来讨论去 这个礼拜最终已经确定 虽然不是我想要的结果 但是我想时间已经不能再等人了 总要人做出牺牲 网站在排名方面一直没有太多的变化 SNS还是准备采用di
  • java日期和时间戳相互转换(实际项目开发总结)

    第一步 改变数据库中字段类型 我这里用的是bigint类型 第二步 编写转换代码 由于项目中用的都是时间戳 直接抽成工具类了 工具类最下面有测试的main方法 代码都一样 package com anjiplus template gaea
  • 深度学习常用单词

    深度学习英文单词表 英文 缩写 汉语 Absolute value rectification 绝对值整流 Activation Function 激活函数 Accumulated error backpropagation 累积误差反向传
  • proxy代理配置 goproxy 代理配置

    1 百度上搜索 goproxy 2 下载 proxy linux amd64 tar gz 2 1 直接下载地址 该版本 不限制默认数量 调整默认的每秒最大连接数 由默认20改为默认0无限制 https github com snail00
  • Maven配置了junit依赖,jar包已经导入,但是在使用Test测试时报错

    Maven配置了junit依赖 jar包已经导入 但是在使用Test测试时报错 作用域问题 每一个依赖都有一个scope标签标示这个依赖可以在哪里使用 如果作用域为test 那么只能在测试 Test Resource Root 包下使用 一
  • 存储器、运算器、控制器基本结构以及一条指令的执行

    Abstract 此篇文章讲述的是计算机存储器 控制器 运算器的基本结构组成以及指令的具体执行顺序 CPU包括运算器和控制器 而主机主要包括CPU和存储器 内容参考于 哈工大计算机组成原理 刘宏伟 存储器的基本组成 如下图所示 主存由存储体
  • Android获取APP的Package和Activity

    在使用android自动化测试工具中启动应用时 需要填写被测程序的包名和启动的Activity 以下是查看应用包名package和入口activity名称的方法 aapt 使用aapt aapt是sdk自带的一个工具 在sdk builds
  • 糖酵解反应动力学方程的微分方程建模

    糖酵解反应动力学方程的微分方程建模 题目 对于下面的糖酵解反应 设其满足如下动力学方程 d d
  • 服务器卡顿了该如何处理

    服务器卡顿了该如何处理 当Windows系统的服务器出现卡顿问题时 以下是一些常见的故障排除步骤 1 检查网络连接 确保服务器的网络连接正常 检查网络设备 交换机 防火墙等设备 确保它们正常运行 尝试通过其他计算机访问服务器 以确定是否存在
  • jdbc连接MySQL数据库(完整文件+详细说明)

    使用jdbc连接数据库 可以直接在方法中定义url user psd等信息 也可以读取配置文件 但是在web项目中肯定是要使用第二种方式的 为了统一 只介绍第二种方式 步骤 1 创建配置文件db properties 无论是eclipse还
  • VB ListView控件各种操作详解

    Private Sub Form Load ListView1 SmallIcons ImageList1 Object 把ImageList1图标列表控件绑定到 ListView1列表控件中来 ListView1 ListItems Cl
  • nodejs面试官:如何实现jwt鉴权机制?说说你的思路

    一 是什么 JWT JSON Web Token 本质就是一个字符串书写规范 如下图 作用是用来在用户和服务器之间传递安全可靠的信息 在目前前后端分离的开发过程中 使用token鉴权机制用于身份验证是最常见的方案 流程如下 服务器当验证用户
  • 游戏服务器被攻击了怎么办?

    随着互联网的发展 网民数量激增 电子游戏的普及 庞大的玩家数量必然推动游戏市场发展 游戏受到攻击是游戏开发者的痛点 DDOS攻击是流量攻击的一个总称 还包括SYN Flood ACK Flood UDP Flood TCP Flood IC
  • Java按一行一行进行文件的读取或写入

    测试代码 import org junit jupiter api Test import java io import java util Arrays public class FileTest 一行一行读取文件 适合字符读取 若读取中
  • Android 生态消息推送平台介绍

    一 手机厂商平台 华为消息推送服务 华为推送 Push 是为开发者提供的消息推送平台 建立了从云端到手机端的消息推送通道 使应用可以将最新信息及时通知用户 从而构筑良好的用户关系 提升用户的感知和活跃度 推送透传消息 以透传方式将自定义的内
  • Python中“from docx import Document“报错问题以及怎么提取.docx文档中所有的红色字体

    1 Python中 from docx import Document 报错问题 Pycharm中 当我们输入 from docx import Document 报错问题 在Pycharm中 我们若是想要操作word文件 我们就必须要使用
  • 广度优先搜索(1)之树的层序遍历

    文章目录 零 导言 一 例子引入 1 题目描述 2 题目分析 3 算法实现与解释 二 概念定义 1 定义 2 深入理解 3 相关知识 三 相关习题 零 导言 这一系列博客的创作初衷是为了记录自己在刷题过程中对于一些比较经典的并且很哇塞的题型