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

article/2025/9/13 1:38:48

概览

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

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

图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历。
我们根据访问节点的顺序与方式(根据搜索方法),可以分为广度优先(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、一般需存储产生的所有结点,占用的存储空间要比深度优先搜索大得多,因此,程序设计中,必须考虑溢出和节省内存空间的问题


http://chatgpt.dhexx.cn/article/eeT8yiUX.shtml

相关文章

深度优先搜索(DFS),看这一篇就够了。

一&#xff0c;定义&#xff1a; 深度优先搜索的思路和树的先序遍历很像&#xff0c;下面是百度百科上的定义&#xff1a; 深度优先遍历图的方法是&#xff0c;从图中某顶点v出发&#xff1a; &#xff08;1&#xff09;访问顶点v&#xff1b; &#xff08;2&#xff09;依次从…

Python实现深度优先遍历(DFS)和广度优先遍历(BFS)

一&#xff0c;简介 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法&#xff0c;生产上广泛用于拓扑排序&#xff0c;寻路(走迷宫)&#xff0c;搜索引擎&#xff0c;爬虫等&#xff0c;也频繁出现在 leetcode&am…

算法数据结构——图的遍历之深度优先搜索算法(Depth First Search)

1. 深度优先搜索简介 深度优先搜索算法&#xff08;Depth First Search&#xff09;&#xff1a;英文缩写为 DFS。是一种用于搜索树或图的算法。所谓深度优先&#xff0c;就是说每次都尝试向更深的节点走。 深度优先搜索采用了回溯思想&#xff0c;该算法沿着树的深度遍历树的节…

【新书速递】实用安全多方计算导论

安全多方计算&#xff08;MPC&#xff09;是解决数据安全与隐私保护问题的关键安全数据交换技术&#xff0c;近年来发展迅速&#xff0c;但由于MPC涉及复杂的密码学和工程实现技术&#xff0c;行业长期缺乏同时具备MPC研究、应用和实现能力的综合性人才&#xff0c;这阻碍了MPC…

百万富翁问题--安全多方计算

百万富翁问题—安全多方计算 是由图灵奖获得者姚期智提出的。 有A、B两个富翁&#xff0c;A资产i亿元&#xff0c;B资产j亿元&#xff0c;i、j均在0-10范围内&#xff0c;在互不让对方知道自己资产的情况下&#xff0c;比较A和B的资产谁多谁少。 那么如何去比较呢&#xff1f;…

隐私保护技术之安全多方计算

安全多方计算(Secure Multi-Party Computation&#xff0c;SMPC)用于解决一组互不信任的参与方各自持有秘密数据&#xff0c; 协同计算一个既定函数的问题。安全多方计算在保证参与方获得正确计算结果的同时&#xff0c;无法获得计算结果之外的任何信息。 在整个计算过程中&…

基于同态加密体制的安全多方计算

本文首发公众号VenusBlockChain&#xff0c;关注公众号后可免费阅读&#xff01;VenusBlockChain致力于区块链技术研究&#xff0c;传播区块链技术和解决方案、区块链应用落地、区块链行业动态等。有兴趣的小伙伴们&#xff0c;欢迎关注。 安全多方计算&#xff08;Secure Mu…

多方安全计算

说明&#xff0c;本文是转载的&#xff0c;个人觉得作者讲解清晰明了&#xff0c;收录用于学习&#xff0c;原文链接&#xff1a;https://blog.csdn.net/yuxinqingge/article/details/104588197。 如今&#xff0c;互联网已经完成了从IT时代向DT时代转变&#xff0c;数据已经成…

多方安全计算MPC

1.多方安全计算的价值 MPC是密码学的一个重要分支&#xff0c;旨在解决一组互不信任的参与方之间保护隐私的协同计算问题&#xff0c;为数据需求方提供不泄露原始数据前提下的多方协同计算能力。 在目前个人数据毫无隐私的环境下&#xff0c;对数据进行确权并实现数据价值显得…

安全多方计算(MPC)

MPC既适用于特定的算法&#xff0c;如加法、乘法、AES&#xff0c;集合交集等&#xff1b;也适用于所有可表示成计算过程的通用算法。 根据计算参与方个数不同&#xff0c;可分为只有两个参与方的2PC和多个参与方&#xff08;≥3&#xff09;的通用MPC 1&#xff09;安全两方&a…

安全多方计算之二:一文搞懂百万富翁问题

百万富翁问题 1. 解决方案2. 协议描述3. 协议说明4. 协议举例5. 协议扩展 两个百万富翁Alice和Bob想知道他们两个谁更富有&#xff0c;但他们都不想让对方及其他第三方知道自己财富的任何信息&#xff0c;这是由中国计算机科学家、2000年图灵奖获得者姚启智教授于1982年在论文《…

安全多方计算-入门学习笔记(三)

四、基于非噪音的安全多方计算介绍 1概念 非噪音方法一般是通过密码学方法将数据编码或加密&#xff0c;得到一些奇怪的数字&#xff0c;而且这些奇怪的数字有一些神奇的性质&#xff0c;比如看上去很随机但其实保留了原始数据的线性关系&#xff0c;或者顺序明明被打乱但人们…

基于隐私保护的安全多方计算区块链融合技术的智能合约

安全多方计算与区块链的融合技术 SMPC-安全多方计算综述安全的定义安全模型SMPC效率问题 区块链应用&#xff1a;智能合约智能合约的问题SMPC需求引入 基于SMPC的智能合约辅助&#xff1a;MPI协议-效率提升 SMPC-安全多方计算综述 随着物联网、移动计算、大数据、云计算的快速…

安全多方计算之GMW协议

安全多方计算之GMW协议 一、背景 论文原文《How to play any mental game》。作者&#xff1a;Micali S, Goldreich O, Wigderson A. 发表在&#xff1a;Proceedings of the Nineteenth ACM Symp on Theory of Computing, STOC. GMW协议可以同时适用在布尔电路和算术电路&am…

多方安全计算概述

多方安全计算&#xff08;Secure Multi-Party Computation&#xff0c; MPC&#xff09;是密码学的一个分支&#xff0c;在无可信第三方的情况下&#xff0c;仍可安全地按照公开的计算逻辑&#xff0c;进行数据协同计算&#xff0c;并输出结果。 即使参与各方输入的数据只有自…

安全多方计算之一:什么是安全多方计算

安全多方计算 1. 安全多方计算简介2. 基本概念2.1 参与者2.2 攻击者 3. 安全多方计算的模型4. 安全多方计算的密码学工具5. 学习参考 1. 安全多方计算简介 安全多方计算问题SMC&#xff0c;Secure Multi-party Computation&#xff09;由由中国计算机科学家、2000年图灵奖获得…

安全多方计算简介

文章目录 一、安全多方计算定义二、安全多方计算安全模型1.行为模型2.安全门限 三、安全多方计算关键技术1.秘密共享(Secret Sharing, SS)2.不经意传输(Oblivious Transfer, OT)3.混淆电路(Garbled Circuit, GC) 参考资料 一、安全多方计算定义 安全多方计算(Secure Multi-Par…

安全多方计算 # 个人笔记

一个优美令人如痴如醉的领域。 Data is the oil of the 21st century 欢迎读者拍砖和提供本文修改建议。本文长期维护。 第二次编辑于2021/10/20&#xff0c;新增了部分阅读材料&#xff0c;调整了文章内容的组织。 0 研究背景 【最后更新于2021/10/20】 时代背景&#xff1…

Verilog操作符

操作符优先级表 Verilog中的大小(size)与符号 Verilog根据表达式中变量的长度对表达式的值自动地进行调整; Verilog自动截断或扩展赋值语句中右边的值以适应左边变量的长度; 当一个负数赋值给无符号变量如reg时,Verilog自动完成二进制补码计算; 算术运算符 加(+)、减(-…

C语言——操作符详解

目录 一、算术操作符 二、移位操作符 三、位操作符 四、赋值操作符 五、单目操作符 六、关系操作符 七、逻辑操作符 八、条件操作符 九、逗号表达式 十、下标引用、函数调用和结构成员 以上就是C语言中涉及到得操作符&#xff0c;我将用代码实例配合说明&#xff0c…