【基础知识】一文看懂深度优先算法和广度优先算法

2023-11-16

概览

先上个图
在这里插入图片描述

现在我们要访问图中的每个节点,即图的遍历。

图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历。
我们根据访问节点的顺序与方式(根据搜索方法),可以分为广度优先(BFS)和深度优先(DFS),这是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等。

我们分别来介绍

一、深度优先(DFS)

深度优先搜索(Depth-First-Search),简称 DFS。
我们以上图为例,现在需要访问每个节点,且只访问一次,可以看到,图分成了很多之路,

主要思路是从图中一个未访问的顶点 V (比如A)开始,沿着一条路一直走到底,深入到不能再深入为止(够深),然后从这条路尽头的节点回退到上一个节点, 如果上一个节点存在没有探索的分支,便继续探索若没有则继续回退,再从另一条路开始走到底…,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。

这就是暴力穷举,

1.1 图解过程

在这里插入图片描述
1、我们从根节点 A 开始遍历,它相邻的节点有 B,E,先遍历节点 B,再遍历 B 的子节点 C
2、上图中一条路已经走到底了(C是叶子节点,再无可遍历的节点),此时就从 C 回退到上一个节点 B,看下节点 B 是否还有除 C 以外的节点,发现 B有 D节点,然后遍历D,
3、同理,上图中一条路已经走到底了(D是叶子节点,再无可遍历的节点),此时就从 D 回退到上一个节点 B,B的节点都遍历过了,然后在回到A, 同样的逻辑,再到,E、F

1.2 java 实现

package com.test;

import java.util.ArrayList;
import java.util.List;

public class DepthFirstSearch {

    // 定义图结构
    private List<Integer>[] graph;

    // 构造函数,初始化图结构
    public DepthFirstSearch(int numVertices) {
        graph = new ArrayList[numVertices];
        for (int i = 0; i < numVertices; i++) {
            graph[i] = new ArrayList<>();
        }
    }

    // 添加边
    public void addEdge(int v1, int v2) {
        graph[v1].add(v2);
    }

    // 深度优先搜索算法实现
    public void dfs(int start) {
        boolean[] visited = new boolean[graph.length]; // 标记每个顶点是否被访问过
        dfsHelper(start, visited); // 递归实现深度优先搜索算法
    }

    // 递归实现深度优先搜索算法
    private void dfsHelper(int vertex, boolean[] visited) {
        visited[vertex] = true; // 标记当前顶点已被访问过
        System.out.print(geta(vertex)); // 输出当前顶点编号
        for (int neighbor : graph[vertex]) { // 遍历当前顶点的邻居顶点
            if (!visited[neighbor]) { // 如果邻居顶点未被访问过,则递归访问它
                dfsHelper(neighbor, visited);
            }
        }
    }

    private String geta(int index){
        switch (index) {
            case 0:
                return "A";
            case 1:
                return "B";
            case 2:
                return "C";
            case 3:
                return "D";
            case 4:
                return "E";
            case 5:
                return "F";
        }
        return "";
    }

    // 测试代码
    public static void main(String[] args) {
        DepthFirstSearch graph = new DepthFirstSearch(6); // 创建图结构,包含6个顶点
        graph.addEdge(0, 1); // 添加边,
        graph.addEdge(0, 4); // 添加边,
        graph.addEdge(1, 2); // 添加边,
        graph.addEdge(1, 3); // 添加边,
        graph.addEdge(4, 5); // 添加边,
        System.out.print("深度优先搜索结果:"); // 输出深度优先搜索结果
        graph.dfs(0); // 从顶点0开始进行深度优先搜索
    }
}

在这个示例代码中,我们首先定义了一个DepthFirstSearch类,用于表示图结构。在构造函数中,我们初始化了图结构,并定义了一个addEdge方法,用于添加边。
然后,我们定义了一个dfs方法,用于执行深度优先搜索算法。在dfs方法中,我们首先创建了一个visited数组,用于标记每个顶点是否被访问过。然后,我们调用dfsHelper方法递归实现深度优先搜索算法。
在dfsHelper方法中,我们首先标记当前顶点已被访问过,并输出当前顶点编号。然后,我们遍历当前顶点的邻居顶点,如果邻居顶点未被访问过,则递归访问它。
最后,我们在测试代码中创建了一个包含6个顶点的图结构,并从顶点0开始进行深度优先搜索。运行测试代码后,输出深度优先搜索结果为:ABCDEF。

深度优先搜索结果:ABCDEF

二、广度优先(BFS)

广度优先遍历是首先把起点相邻的几个点探索完成,然后去探索距离起点稍远一些(隔一层)的点,然后再去玩探索距离起点更远一些(隔两层)的点… 是一层一层的向外探索。

遍历规则:
1)先访问完当前顶点的所有邻接点。(应该看得出广度的意思)
2)先访问顶点的邻接点先于后访问顶点的邻接点被访问。

2.1 图解过程

在这里插入图片描述

2.2 java代码实现

import java.util.*;  
  
public class BFS {  
    // 定义图结构  
    private List<List<Integer>> graph;  
  
    // 构造函数,初始化图结构  
    public BFS(int numVertices) {  
        graph = new ArrayList<>();  
        for (int i = 0; i < numVertices; i++) {  
            graph.add(new ArrayList<>());  
        }  
    }  
  
    // 添加边  
    public void addEdge(int v1, int v2) {  
        graph.get(v1).add(v2);  
        graph.get(v2).add(v1);  
    }  
  
    // 广度优先搜索算法实现  
    public void bfs(int start) {  
        boolean[] visited = new boolean[graph.size()]; // 标记每个顶点是否被访问过  
        Queue<Integer> queue = new LinkedList<>(); // 创建队列,用于存储待访问的顶点  
        visited[start] = true; // 标记起始顶点已访问过  
        queue.offer(start); // 将起始顶点加入队列中  
        while (!queue.isEmpty()) { // 当队列非空时,继续遍历队列中的顶点  
            int vertex = queue.poll(); // 取出队列头部顶点  
            System.out.print(vertex + " "); // 输出当前顶点编号  
            for (int neighbor : graph.get(vertex)) { // 遍历当前顶点的邻居顶点  
                if (!visited[neighbor]) { // 如果邻居顶点未被访问过,则标记为已访问过,并加入队列中  
                    visited[neighbor] = true;  
                    queue.offer(neighbor);  
                }  
            }  
        }  
    }  
  
    // 测试代码  
    public static void main(String[] args) {  
        BFS graph = new BFS(6); // 创建图结构,包含6个顶点  
        graph.addEdge(0, 1); // 
        graph.addEdge(0, 4); // 
        graph.addEdge(1, 2); //   
        graph.addEdge(1, 3); // 
        graph.addEdge(4, 5); // 
        System.out.print("广度优先搜索结果:"); // 输出广度优先搜索结果  
        graph.bfs(0); // 从顶点0开始进行广度优先搜索  
    }  
}

在这个示例代码中,我们首先定义了一个BFS类,用于表示图结构。在构造函数中,我们初始化了图结构,并定义了一个addEdge方法,用于添加边。
然后,我们定义了一个bfs方法,用于执行广度优先搜索算法。在bfs方法中,我们首先创建了一个visited数组,用于标记每个顶点是否被访问过。
然后,我们创建了一个队列,用于存储待访问的顶点。我们将起始顶点加入队列中,并标记为已访问过。然后,我们开始遍历队列中的顶点。对于每个队列头部顶点,我们输出其编号,并遍历其邻居顶点。如果邻居顶点未被访问过,则将其标记为已访问过,并加入队列中。
最后,我们使用一个测试代码来测试我们的广度优先搜索算法实现。运行测试代码后,输出广度优先搜索结果为:0 1 2 3 4 5。

三、总结

3.1 深度优先遍历:

1、对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历(我们前面使用的是先序遍历)。
2、不全部保留结点,占用空间少;有回溯操作(即有入栈、出栈操作),运行速度慢。
3、一般无回溯操作,即入栈和出栈的操作,所以运行速度比深度优先搜索要快些

3.2 广度优先遍历:

1、又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止
2、保留全部结点,占用空间大; 无回溯操作(即无入栈、出栈操作),运行速度快。
3、一般需存储产生的所有结点,占用的存储空间要比深度优先搜索大得多,因此,程序设计中,必须考虑溢出和节省内存空间的问题

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

【基础知识】一文看懂深度优先算法和广度优先算法 的相关文章

随机推荐

  • mysql 触发器

    触发器 当对某张表进行 INSERT DELETE UPDATE 操作时 会自动触发定义的触发器中的操作 顾名思义 当我们为某张表定义触发器后 向表中添加 删除 修改数据时 会触发触发器中定义的操作 触发器像是一个事件的监听 一旦监听的事件
  • springboot校园二手物品交易平台 毕业设计源码03373

    目 录 摘要 1 绪论 1 1 研究背景 1 2国内外研究现状 1 3论文结构与章节安排 2平台分析 2 1 可行性分析 2 2 系统流程分析 2 2 1 数据流程 3 3 2 业务流程 2 3 系统功能分析 2 3 1 功能性分析 2 3
  • 大数据标准化白皮书(2020版) 附下载地址

    大数据是新时代最重要的 数字金矿 是全球数字经济发展的核心动能 数据资源如同农业时代的土地 劳动力 工业时代的技术 资本 已经成为信息 时代重要的基础性战略资源和关键生产要素 是推动经济发展质量变革 效率变 革 动力变革的新引擎 不断驱动人
  • python爬取推特图片_twitter图片视频批量下载

    import requests import re from urllib request import urlretrieve import os import ssl ssl create default https context s
  • 试看5分钟视频python_Python面试应急5分钟!

    不论你是初入江湖 还是江湖老手 只要你想给自己一个定位那就少不了面试 面试的重要性相信大家都知道把 这就是我们常说的 第一印象 给大家说一下我的面试心得把 面试前的紧张是要的 因为这能让你充分准备 面试时的紧张是绝对要避开的 因为这可能导致
  • open source 3d map_3D视觉技术在机器人抓取作业中的应用实例

    原标题 3D视觉技术在机器人抓取作业中的应用实例 关键词 3D视觉 工业机器人 抓取 1 引言 3D视觉技术作为新兴的技术领域还存在很多亟待解决的问题 但2D视觉已不能满足空间抓取的应用要求 与2D视觉相比 3D视觉技术的优点有 1 3D视
  • C++ 创建桌面快捷方式

    include
  • 白盒测试——基本路径测试

    基本路径测试是将程序流程图转化为控制流图 通过分析控制结构的环路复杂性 进而找出路径的基本独立集 最终导出测试用例 基本独立集 从基本独立集导出的测试用例保证对程序中的每一条语句至少执行一次 控制流图 定义 百度百科 是一个过程或程序的抽象
  • 若依开关使用

  • OpenLayers 6加载各种地图源的方法(天地图、百度、高德、ArcGIS、Bing、OSM、Google等)

    前言 OpenLayers是一个用于开发WebGIS客户端的JavaScript包 OpenLayers 支持多种常用的地图来源 包括天地图 百度地图 高德地图 ArcGIS地图 Bing地图 OSM地图 Google地图等 一 加载天地图
  • 3D游戏编程——空间与运动

    3D游戏编程 空间与运动 1 简答并用程序验证 游戏对象运动的本质是什么 答 游戏对象运动的本质就是使用矩阵变换 平移 旋转 缩放 改变游戏对象的空间属性 我们做的游戏关键就是游戏对象在每一帧图像上怎么变换 最直观的就是观察我们每个对象的T
  • CSS SASS 外部引入的scss文件中,不能用嵌套写法

    小记录 在vue文件中引入scss文件中 不能正常使用sass语法 发现是引入方式的问题
  • 【自我提升】Spring Data JPA之Specification动态查询详解

    写在前面 刷完Spring Data JPA的课后 发现Specification动态查询还挺有意思的 还应用到了规约设计模式 在此记录下学习过程和见解 目录 一 应用场景 二 源码解析 三 规约模式 四 实际应用 一 应用场景 1 简介
  • 云数据库知识学习——概述

    一 云计算是云数据库兴起的基础 云计算是分布式计算 并行计算 效用计算 网络存储 虚拟化 负载均衡等计算机和网络技术发展融合的产物 云计算是由一系列可以动态升级和被虚拟化的资源组成的 用户无需掌握云计算的技术 只要通过网络就可以访问这些资源
  • function XX declared implicitly

    stm32 keilMDK出现warning function XX declared implicitly 原创 2014年08月26日 14 50 47 26281 warning 223 D function CLR TX DATA
  • 枚举类,属性循环---(枚举类循环)通过名称取值

    代码示例 public enum DomeEnum AA 1 张三 BB 2 李四 CC 3 王五 DD 4 赵六 EE 5 李七 private Integer code private String name DomeEnum Inte
  • Qt 官方示例

    哈喽 我是老吴 最近又玩了一下 Qt 给大家分享一点 Qt 相关的基础知识吧 我个人非常喜欢 Qt 它简直就是我这个 C 手残党的利器 学习 Qt 的最佳途径应该是阅读官方的手册和示例 今天要分享的就是 Qt 官方提供的一个示例 http
  • 一种针对夏克哈特曼波前传感器质心数据求解波前斜率的处理方法

    一 导出质心数据 针对夏克哈特曼波前传感器 型号 索雷博 导出的质心数据 Save Centroid Date 本文提供一种基于质心数据的斜率矩阵获取及波前重构方法 图 1 哈特曼波前传感器导出质心数据 二 斜率矩阵求解 首先 通过Wave
  • 2023上半年京东运动鞋服市场数据分析(京东数据运营)

    大众线下运动生活恢复 掀起新一轮户外潮流 运动热潮迭起 由此产生的运动鞋服及专业装备需求 为运动品牌们带来了诸多增长机会 近日各大运动品牌陆续发布上半年财报 回答了品牌对复苏机遇 发展挑战的应对情况 接下来结合具体数据 我们一起来看一下运动
  • 【基础知识】一文看懂深度优先算法和广度优先算法

    概览 先上个图 现在我们要访问图中的每个节点 即图的遍历 图的遍历是指 从给定图中任意指定的顶点 称为初始点 出发 按照某种搜索方法沿着图的边访问图中的所有顶点 使每个顶点仅被访问一次 这个过程称为图的遍历 我们根据访问节点的顺序与方式 根