02_02_广度优先搜索(Breadth-First Search,BFS)

2023-11-08

广度优先搜索(Breadth-First Search,BFS)

广度优先搜索(Breadth-First Search,BFS)介绍:

是一种图遍历算法,其原理是逐层遍历图的节点。BFS从起始节点开始,先访问起始节点的所有邻居节点,然后再逐层访问其他邻居节点。

广度优先搜索(Breadth-First Search,BFS)原理:
  1. 选择一个起始节点,并将其标记为已访问。
  2. 将起始节点放入队列(通常是使用队列数据结构实现BFS)。
  3. 当队列不为空时,执行以下步骤:
    ● 从队列中取出一个节点作为当前节点。
    ● 访问当前节点,并进行相应的操作。
    ● 将当前节点的所有未访问的邻居节点加入队列,并标记为已访问。
  4. 如果队列为空,表示已经遍历完所有节点,算法结束。
Java 代码实现:
package com.algorithm.graph;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class BFS {

    /**
     * 测试方法
     *
     * @param args todo
     */
    public static void main(String[] args) {

        /**
         * 创建有 6 个节点的图对象
         */
        BFSGraph graph = new BFSGraph(6);

        /**
         * 添加节点
         */
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(1, 3);
        graph.addEdge(2, 4);
        graph.addEdge(2, 5);

        System.out.println("Breadth-First Traversal (starting from vertex 0):");

        /**
         * 调用 BFS 算法遍历节点
         */
        graph.BFS(0);
    }

}

/**
 * BFS 算法实现原理
 * <p>
 * 1.选择一个起始节点,并将其标记为已访问。
 * 2.将起始节点放入队列(通常是使用队列数据结构实现BFS)。
 * 3.当队列不为空时,执行以下步骤:
 * 从队列中取出一个节点作为当前节点。
 * 访问当前节点,并进行相应的操作。
 * 将当前节点的所有未访问的邻居节点加入队列,并标记为已访问。
 * 4.如果队列为空,表示已经遍历完所有节点,算法结束。
 */
class BFSGraph {

    /**
     * 节点数量
     */
    private int numVertices;

    /**
     * 邻接表
     */
    private List<List<Integer>> adjacencyList;

    /**
     * 构造方法,将所有的节点全部存储在 ArrayList 集合中
     *
     * @param numVertices 节点数量
     */
    public BFSGraph(int numVertices) {
        this.numVertices = numVertices;
        this.adjacencyList = new ArrayList<>(numVertices);
        for (int i = 0; i < numVertices; i++) {
            adjacencyList.add(new ArrayList<>());
        }
    }

    /**
     * 添加边到邻接表
     *
     * @param source      起始节点
     * @param destination 终点节点
     */
    public void addEdge(int source, int destination) {
        adjacencyList.get(source).add(destination);
        /**
         * 如果是无向图,需要添加反向边
         */
        adjacencyList.get(destination).add(source);
    }

    /**
     * 算法实现
     *
     * @param startVertex 开始节点
     */
    public void BFS(int startVertex) {

        /**
         * 标记节点是否已被访问
         */
        boolean[] visited = new boolean[numVertices];

        /**
         * 使用队列来存储待访问的节点
         */
        Queue<Integer> queue = new LinkedList<>();

        /**
         * 从起始节点开始,将其标记为已访问并加入队列
         * 队列特点:先入先出
         */
        visited[startVertex] = true;
        queue.add(startVertex);

        /**
         * 遍历队列
         */
        while (!queue.isEmpty()) {
            int currentVertex = queue.poll();

            /**
             * 打印节点
             */
            System.out.print(currentVertex + " ");

            List<Integer> neighbors = adjacencyList.get(currentVertex);
            for (int neighbor : neighbors) {
                if (!visited[neighbor]) {
                    /**
                     *将未访问的邻居节点标记为已访问
                     */
                    visited[neighbor] = true;

                    /**
                     * 将节点加入队列
                     */
                    queue.add(neighbor);
                }
            }
        }
    }
}
代码简单解释:

在这个代码示例中,我们定义了一个Graph类来表示图数据结构,包括节点数量numVertices和邻接表adjacencyList。addEdge方法用于添加边到邻接表,注意在无向图中需要添加反向边。

在BFS方法中,我们使用一个布尔数组visited来标记节点是否已被访问,并使用一个队列queue来存储待访问的节点。我们从起始节点开始,将其标记为已访问并入队列。然后,进入循环直到队列为空。在循环中,我们从队列中取出一个节点,打印该节点,并将其未访问的邻居节点标记为已访问并入队列。

在主函数中,我们创建一个Graph对象,并通过addEdge方法添加边。然后调用BFS方法以广度优先的方式遍历图,从起始节点0开始。

程序执行结果:
Breadth-First Traversal (starting from vertex 0):
0 1 2 3 4 5 
Process finished with exit code 0
备注:

广度优先搜索算法的原理是逐层遍历,从起始节点开始,先访问起始节点的所有邻居节点,然后逐层访问下一层的邻居节点。这样可以保证从起始节点到其他节点的最短路径被优先访问到。BFS算法还可以用于解决一些问题,如寻找最短路径、连通性检测、图的遍历等。

广度优先搜索(Breadth-First Search,BFS)算法图示:

假设我们有以下图结构:

     0
    / \
   1   2
  /   / \
 3   4   5

开始时,选择起始节点0进行广度优先搜索。我们从节点0开始,然后按照层级逐层访问节点的邻居节点。首先,我们访问节点0的邻居节点1和2。然后,访问节点1的邻居节点3,访问节点2的邻居节点4和5。

下面是BFS算法执行的过程描述:

  1. 选择起始节点0,并将其标记为已访问。
     0*
    / \
   1   2
  /   / \
 3   4   5
  1. 访问节点0的邻居节点1和2,并将它们标记为已访问。
     0*
    / \
   1*  2*
  /   / \
 3   4   5
  1. 访问节点1的邻居节点3,并将其标记为已访问。
     0*
    / \
   1*  2*
  /   / \
 3*  4   5
  1. 访问节点2的邻居节点4和5,并将它们标记为已访问。
     0*
    / \
   1*  2*
  /   / \
 3*  4*  5*

最终,BFS算法的遍历路径为0-1-2-3-4-5。

总结:

通过图的可视化,我们可以更直观地理解BFS算法的执行过程。在每一层级中,我们先访问当前层级的所有节点,然后再进入下一层级的节点。这种层级遍历的方式可以帮助我们找到起始节点到其他节点的最短路径,并保证我们按照距离逐层遍历图的节点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

02_02_广度优先搜索(Breadth-First Search,BFS) 的相关文章

  • 如何在 Java 中验证从 Azure AD B2C 生成的 JWT 令牌?

    我正在寻找 Java 代码示例来验证 Azure AD B2C 令牌 我们可以使用哪些依赖项 所有 JWT 令牌的 JWT 令牌验证步骤或代码是否相同还是会有所不同 我们的项目中没有使用 Spring Security 有大量的图书馆her
  • JAVA_HOME环境变量和Java JDK趣事

    我想让 Java 在 1 6xxx 上运行 我更改了 JAVA HOME 变量并将其指向目录 C Program Files Java jdk1 6 0 16 我重新启动 PC 我想我可以检查我的机器指向哪个版本的 Java 但它仍然指向旧
  • 方法重载。你能过度使用它吗?

    当定义多个使用不同过滤器返回相同形状的数据的方法时 什么是更好的做法 显式方法名称或重载方法 例如 如果我有一些产品并且我正在从数据库中提取 显式方式 public List
  • 单击链接时如何将另一个 JSP 页面注入到

    我在一个JSP页面中有两个不同的部分 其中一个包含链接菜单 单击时 div2 id content 会相应加载不同的页面 我正在做类似的事情 div ul class navbar li a href Login jsp Login a l
  • cygwin有java sdk吗?

    cygwin有java sdk吗 如果有一个使用 cygwin 文件系统和 X windows 进行显示的本机 cygwin 实现 那就太好了 不幸的是我不知道这样的版本 我认为移植 OpenJDK 也需要付出很大的努力 但我还没有尝试过
  • JTree 避免重新加载后崩溃

    我正在尝试找到解决崩溃问题的方法JTree重新加载后 情况 JTree Office A Office A 1 Office A 1 1 Office A 1 2 Office B Office B 1 Office B 1 1 Offic
  • Spring批量写入器限制

    我正在工作 Spring Batch 项目 从数据库读取记录然后写入rabbitmq 然后发送到HTTP消息网关 网关有150TPS我需要将我的应用程序限制为 150TPS 有没有办法带弹簧批的油门或者还有其他更好的方法吗 你能行的 在 S
  • 从 java 类生成 xsd 的实用程序

    我想为以下类生成 xsd public class Node private String value private List
  • java.time.LocalDate 到 java.util.Date

    转换的最佳方式是什么java time LocalDate to java util Date Date from dateToReturn atStartOfDay ZoneId systemDefault toInstant 我一直在尝
  • 枚举内的枚举

    这不是我被卡住的问题 而是我正在寻找一种简洁的方式来编写我的代码 本质上 我正在编写一个事件驱动的应用程序 用户触发事件 事件被发送到适当的对象 然后对象处理事件 现在我正在编写偶数处理程序方法 我希望使用 switch 语句来确定如何处理
  • 声纳要求将这一领域定为最终目标

    我的程序中有以下代码 在与 Maven 集成后 我正在运行 SonarQube 5 对其进行代码质量检查 我面临这个错误 将此 public static processStatus 字段设为最终字段 将此 public static pr
  • 如何在 Java 中读取/转换 InputStream 为字符串?

    如果你有一个java io InputStream对象 您应该如何处理该对象并生成一个String 假设我有一个InputStream包含文本数据 我想将其转换为String 例如我可以将其写入日志文件 最简单的方法是什么InputStre
  • 如何使 JFileChooser 仅显示具有某些特定名称 Java 的文件夹

    有什么方法可以让 JFileChooser 加载时仅显示名称为 Hello 的文件夹 这是我的代码 它显示所有文件夹以及扩展名为 py 和 java 的文件 我想添加文件夹名称限制 FileNameExtensionFilter filte
  • 如何保存/加载 BigInteger 数组

    我想保存 加载BigInteger数组传入 传出 SharedPreferences 如何做呢 例如对于以下数组 private BigInteger dataCreatedTimes new BigInteger 20 Using Gso
  • Spring portlet mvc:@Valid 似乎不起作用

    我创建了一个 bean 类并在我的控制器中使用它 但它似乎不起作用 也就是说 即使我输入了无效的年龄 result hasErrors仍然是假的 豆类 public class User Min 13 private int age pri
  • 使用mapstruct映射不同类型列表的元素

    我们正在映射一个对象 该对象具有一个对象列表 这些对象都实现了父接口 但可能具有不同的实现 但当我们映射列表时 似乎只有来自 ParentClass 的值被映射 而不是来自子类的值 但直接映射子进程就可以了 public class Par
  • 当 javadoc 未附加到依赖项时,如何将 javadoc 引用到 Maven 的 eclipse 插件中的依赖项

    我在开发中使用 Eclipse Maven 和 Java 我使用 Maven 下载依赖项 jar 文件和 javadoc 如果可用 并使用 Maven 的 eclipse 插件为 Eclipse 生成 project 和 classpath
  • 如何在 VSCode 中热重载 Tomcat 服务器

    我正在从 Eclipse IDE VSCode 分别用于编码 Java servlet 和 HTML CSS JS 网页 迁移到仅使用 Visual Studio Code 因为它的轻量级 我为 VSCode 安装了几个 Java 扩展 R
  • Android 中的自定义相机应用程序问题 - 旋转 270、拉伸捕获视图且未获取所有功能

    我从代码中得到了帮助https github com josnidhin Android Camera Example https github com josnidhin Android Camera Example 但面临一些问题 例如
  • 最新版本 6.* Struts2 支持 Tomcat 10 吗? [复制]

    这个问题在这里已经有答案了 最新版本 6 Struts2 支持 Tomcat 10 吗 异常启动过滤器 struts2 java lang ClassCastException class org apache struts2 dispat

随机推荐

  • VS2013配置SQLite数据库

    1 下载SQLite相关文件 官网 https sqlite org download html 下载这两个文件 3 编译 解压文件 里面存在两个文件 打开windows下的cmd 找到vs2013的安装路径下的lib exe所在的文件夹
  • 人工智能-搜索----启发式搜索

    搜索算法的形式化描述 lt 状态state 动作motion 状态转移state transition 路径path 测试目标test target gt 一 启发式搜索 有信息搜索 Heuristic Search 代表算法 贪婪最佳优先
  • latex 图片跑到引用后的解决办法

    问题描述 双栏情况下 当正文 参考文献占不到一页 而此时你的图片又刚好占了至少半页 此时图片就会被抵到参考文献后 解决办法 要想将参考文献调整到图片后 可以在论文开头引入包 usepackage section placeins 但这样的话
  • 用c语言开发一个安卓APP,c语言开发的app-用c语言可以开发app吗

    通常 IOS应用使用C 和对象的C 以写的 但到的xcode通过该程序 您可以写信给重用OC A应用程序也可以用一个OC C 结合起来写 我读了一外地开发商说 代码app1000行 他开发800是C 200条OC 电话软件 c编程语言都可以
  • 腾讯云Linux服务器搭建(二) DNS设置

    主机是用支付宝交钱 从付款到拿到主机用了20分钟左右吧 拿到后上去确认了配置是否相符 一切确认无误后 先把域名的DNS设置到主机上 然后再开始办理备案相关手续 域名解析 域名原来是从万网买的 现在万网早就被阿里收购了 只能去阿里云找了 直接
  • php curl 发起get和post网络请求.note

    curl介绍 curl是一个开源的网络链接库 支持http https ftp gopher telnet dict file and ldap 协议 之前均益介绍了python版本的pycurl http junyiseo com pyt
  • ClickHouse替换MySQL作为数仓APP层

    一 ClickHouse 是什么 二 业务问题 三 ClickHouse实践 四 遇到的坑 五 总结 一 ClickHouse 是什么 ClickHouse 是一个用于联机分析 OLAP 的列式数据库管理系统 DBMS 我们首先理清一些基础
  • 【转载】CNN模型复杂度(FLOPs、MAC)、参数量与运行速度

    备忘 作者写错了 1次乘加运算等于2次浮点运算 但在数值上正好反过来 即1 FLOPs 2 MACs 例如对于卷积运算的计算是 其MACs 参数m 输出尺寸 n 而FLOPs 2 MACs Nvidia团队论文里面写的是对的 2倍 CNN模
  • SQLServer导入导出excel及常见问题

    前几天考试系统导入导出学生信息 初次接触导入导出 为sqlserver和excel的数据传递方法之简和MS产品的高效兼容所震惊 但也遇到各种各样问题 在此介绍SQLServer导入导出excel方法及遇到的问题 SQLServer导出Exc
  • java 中Date日期类型

    4 日期相关 把1970年1月1日当做了时间原点 以毫秒值为单位 4 1 获得当前时间 System currentTimeMillis public class DateTest public static void main Strin
  • ifstream 和 ofstream 文件中读取和写入操作

    导读 ofstream是从内存到硬盘 ifstream是从硬盘到内存 其实所谓的流缓冲就是内存空间 在C 中 有一个stream这个类 所有的I O都以这个 流 类为基础的 包括我们要认识的文件I O stream这个类有两个重要的运算符
  • XGBoost和LightGBM的比较

    目录 1 XGBoost sgboost中树节点分裂时所采用的公式 xgboost的分裂步骤 xgboost总结 LightGBM 基于决策树算法的分布式梯度提升框架 LightGBM在模型的训练速度和内存方面的优化 LightGBM的le
  • arima模型 p q d 确定_【干货】时间预测之 ARIMA模型

    ARIMA 是 AutoRegressive Integrated Moving Average的简称 看起来很复杂 其实这个模型本身是多个模型的叠加或者说混合 AR 自相关模型 AutoRegressive MA 移动平均模型 Movin
  • Python显示目录的树形结构

    转自 http blog chinaunix net uid 21374062 id 5198995 html Python显示目录的树形结构 coding utf 8 仿Linux命令tree生成树形目录结构 并汇总当前目录下文件总算 A
  • pes2017服务器维护时间,PES2017授权详情与球场数据包发布时间

    East Dorsetshire AFC Bournemouth BOU Lancashire Claret Burnley BRN London FC Chelsea CHE South Norwood Crystal Palace CR
  • python:多维数组变一维数组

    python 多维数组变一维数组 b a flatten 将多维数组变为1维数组 具体代码如下 import numpy as np 1 随机生成一个4行3列的多维数组a a np random randn 4 3 print a prin
  • selenium自动化,更新到最新的chrome驱动

    很久没有做自动化了 最近想要熟悉下 发现之前的chrome驱动器与现在的chrome浏览器版本不匹配了导致报错 提示如下 raise exception class message screen stacktrace selenium co
  • (已解决)显卡(N卡)设置独显后,指定程序依旧使用集显渲染

    显卡 N卡 设置独显后 指定程序依旧使用集显渲染 设置流程如下 设置流程如下 1 打开 nvdia 控制面板 2 设置全局为独显 3 修改指定程序为独显 4 以上几步若无效 则按如下修改 选择对应的程序
  • Linux安装nginx

    Linux安装nginx 1 下载 2 准备目录 3 上传 解压 5 设置安装路径 如果 报错 gcc pcre 6 编译 7 安装 8 启动 9 其他命令 10 判断Nginx配置是否正确命令 11 开放nginx默认端口号80 12 访
  • 02_02_广度优先搜索(Breadth-First Search,BFS)

    广度优先搜索 Breadth First Search BFS 广度优先搜索 Breadth First Search BFS 介绍 是一种图遍历算法 其原理是逐层遍历图的节点 BFS从起始节点开始 先访问起始节点的所有邻居节点 然后再逐层