深度优先搜索与广度优先搜索,你知道它们的区别吗?

什么是深度优先搜索?

深度优先搜索(DFS,Depth-First Search)是算法中的一种重要的搜索策略。它的核心思想是“深入探索,直至无路可走,然后再回溯”。这种策略在许多问题中都有着广泛的应用,例如图的遍历、路径查找、解决迷宫问题等等。

让我们通过一个生活中的例子来理解深度优先搜索。假设你正在玩一个迷宫游戏,你需要从迷宫的入口找到出口。你可以选择往前走,直到遇到死胡同,然后再回头,选择另外一个方向继续前进,直到找到出口。这个过程,就是深度优先搜索的一个形象展现。

深度优先搜索的过程就像是在一条路上不断探索,直到这条路走不通,然后再回溯,寻找其他的路。这种策略虽然可能会让我们走一些冤枉路,但它却能保证我们遍历到每一个可能的路口,不会漏掉任何一个可能的解决方案。

明白了深度优先搜索的基本概念和核心思想后,接下来我们将学习如何通过编程实现这种搜索策略。

深度优先搜索的实现

深度优先搜索的实现并不复杂,但却需要我们对递归或栈有深入的理解。下面,让我们通过一个Java代码示例来了解如何实现深度优先搜索。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class OneMoreClass {// 用于标记节点是否被访问过 private Map<Integer, Boolean> visited = new HashMap<>();// 邻接表表示的图 private Map<Integer, List<Integer>> graph = new HashMap<>();/*** 添加边** @param u 起点* @param v 终点*/public void addEdge(int u, int v) {// 初始化邻接表 if (!graph.containsKey(u)) {graph.put(u, new ArrayList<>());visited.put(u, false);}if (!graph.containsKey(v)) {graph.put(v, new ArrayList<>());visited.put(v, false);}// 在u的邻接表中添加v graph.get(u).add(v);}/*** 深度优先搜索** @param v 当前访问的节点*/public void dfs(int v) {// 标记当前节点已访问 visited.put(v, true);System.out.print(v + " ");// 访问v的所有未被访问过的邻居节点 for (int neighbor : graph.get(v)) {if (!visited.get(neighbor)) {dfs(neighbor);}}}public static void main(String[] args) {OneMoreClass dfs = new OneMoreClass();dfs.addEdge(0, 1);dfs.addEdge(0, 2);dfs.addEdge(1, 2);dfs.addEdge(2, 0);dfs.addEdge(2, 3);dfs.addEdge(3, 3);System.out.println("深度优先搜索(从节点2开始):");dfs.dfs(2);}
}

在这个例子中,我们首先定义了一个图,然后通过深度优先搜索遍历了这个图。我们使用邻接表来表示图,并使用一个HashMap来记录每个节点是否被访问过。在深度优先搜索中,我们首先访问一个节点,然后递归地访问它的所有未被访问过的邻居节点。运行结果如下:

深度优先搜索(从节点2开始):
2 0 1 3

这段代码虽然简短,但却包含了深度优先搜索的核心思想。通过递归,我们可以轻松地实现深度优先搜索,遍历所有的节点。

然而,深度优先搜索并非没有问题。在实际使用中,我们可能会遇到一些问题,例如递归深度过大导致的栈溢出问题,或者是非递归实现时栈的使用不当等。接下来,让我们来了解一下广度优先搜索。

什么是广度优先搜索?

在深入浸润了深度优先搜索的世界之后,我们来到了另一个重要的概念——广度优先搜索。如果说深度优先搜索是一种勇敢的冒险者,深入洞穴的每一个角落,那么广度优先搜索则像是一位细心的园丁,逐层照顾每一朵花儿,不让任何一处被忽视。

广度优先搜索(Breadth-First Search,BFS)是一种在树(Tree)或图(Graph)这样的数据结构中进行搜索的算法。它的特点是一层一层地进行搜索,每一层的节点都会被访问到,然后再进入下一层。这种方式就好比我们在寻找某个城市的地铁站,先从起点站开始,然后逐站寻找,直到找到目标站为止。

接下来,我们将深入探讨如何实现广度优先搜索,以及在实际应用中如何使用它来解决问题。

广度优先搜索的实现

在深入理解了广度优先搜索的基本概念之后,让我们一起来探讨如何用Java语言将其实现。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;public class OneMoreClass {// 用于标记节点是否被访问过 private Map<Integer, Boolean> visited = new HashMap<>();// 邻接表表示的图 private Map<Integer, List<Integer>> graph = new HashMap<>();/*** 添加边** @param u 起点* @param v 终点*/public void addEdge(int u, int v) {// 初始化邻接表 if (!graph.containsKey(u)) {graph.put(u, new ArrayList<>());visited.put(u, false);}if (!graph.containsKey(v)) {graph.put(v, new ArrayList<>());visited.put(v, false);}// 在u的邻接表中添加v graph.get(u).add(v);}/*** 广度优先搜索** @param v 当前访问的节点*/public void bfs(int v) {// 创建一个队列,用于存储待访问的节点 Queue<Integer> queue = new LinkedList<>();queue.add(v);visited.put(v, true);while (!queue.isEmpty()) {int node = queue.poll();System.out.print(node + " ");// 访问node的所有未被访问过的邻居节点 for (int neighbor : graph.get(node)) {if (!visited.get(neighbor)) {queue.add(neighbor);visited.put(neighbor, true);}}}}public static void main(String[] args) {OneMoreClass bfs = new OneMoreClass();bfs.addEdge(0, 1);bfs.addEdge(0, 2);bfs.addEdge(1, 2);bfs.addEdge(2, 0);bfs.addEdge(2, 3);bfs.addEdge(3, 3);System.out.println("广度优先搜索(从节点2开始):");bfs.bfs(2);}
}

我们使用了一个队列来存储待访问的节点,而不是直接递归访问。这是因为广度优先搜索是按照距离顺序访问节点的,即先访问距离当前节点最近的节点,然后再访问距离当前节点稍远一些的节点,以此类推。运行结果如下:

广度优先搜索(从节点2开始):
2 0 3 1

这种实现方式看似简单,但其中蕴含的深度却不容忽视。在实际应用中,我们可能会遇到各种各样的问题,比如如何处理图中的环,如何优化搜索效率等等。

深度优先搜索与广度优先搜索的比较

在我们深入了解深度优先搜索和广度优先搜索的特性后,现在我们来比较一下这两种搜索策略的优缺点,以及它们在不同场景下的应用。

深度优先搜索,如同其名,它的特点是尽可能深地搜索树的分支。这种策略在搜索大树时非常有效,因为它可以快速找到解决方案,或者在没有解决方案的情况下,快速排除某些路径。然而,这种策略也有其局限性,例如,它可能会在搜索过程中陷入无限循环。为了避免这种情况,我们通常需要在实现深度优先搜索时,加入一些特殊的检查机制。

广度优先搜索则是一种层次遍历的策略,它会先搜索离根节点最近的节点,然后再搜索下一层的节点。这种策略在搜索最短路径问题时非常有效,因为它总是先搜索离根节点最近的路径,所以一旦找到解决方案,那么这个解决方案就是最短的。然而,广度优先搜索需要存储所有的节点,因此在空间复杂度上,通常会比深度优先搜索要大。

让我们通过一个实际的例子来理解这两种搜索策略。假设我们想要找到从A地点到B地点的路线。如果我们使用深度优先搜索,那么我们可能会先找到一条从A到B的路线,但这条路线可能不是最短的。如果我们使用广度优先搜索,我们会先找到所有从A出发可以到达的地点,然后再从这些地点出发,找到可以到达B的地点。这样,我们找到的第一条路线,就是最短的路线。

在实际的应用中,我们应该根据问题的特性,选择最适合的搜索策略。例如,如果我们需要找到所有可能的解决方案,那么深度优先搜索可能会更有效。而如果我们需要找到最短的解决方案,那么广度优先搜索可能会更合适。

总结

我们深入探讨了深度优先搜索和广度优先搜索,这两种广泛应用的搜索策略。我们通过生动的例子和简单的代码示例,理解了它们的基本概念,实现方法,以及在实际问题中的应用。

深度优先搜索和广度优先搜索,就如同我们生活中的两种不同的决策策略。深度优先搜索,就像是一位勇敢的冒险家,愿意深入探索未知的世界,即使可能会走一些冤枉路,也不愿意错过任何一个可能的机会。而广度优先搜索,就像是一位谨慎的规划者,他会仔细地考虑每一步的选择,以最高的效率,找到最优的解决方案。

深度优先搜索和广度优先搜索是我们解决问题的重要工具。但是,我们不能盲目地选择使用哪一种搜索策略,而应该根据问题的特性,选择最适合的策略。这就像我们在生活中面临选择时,不能盲目地跟随别人,而应该根据自己的情况,做出最适合自己的决定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/828324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dial tcp 192.168.0.190:443: connect: connection refused

1、场景 用nerdctl登录镜像仓库192.168.0.190&#xff08;Harbor&#xff09;&#xff0c;报错 ERRO[0006] failed to call tryLoginWithRegHost error"failed to call rh.Client.Do: Get \"https://192.168.0.190/v2/\": dial tcp 192.168.0.190:…

【数据结构】图(Graph)

文章目录 概念图的存储方式邻接矩阵邻接矩阵表示法邻接矩阵表示法的特点 邻接表邻接表表示法邻接表表示法的特点邻接表表示法的定义与实现查找插入删除其它构造函数析构函数创建图输出图 图的遍历深度优先遍历&#xff08;DFS&#xff09;广度优先遍历 图的连接分量和生成树生成…

C#设计树形程序界面的方法:创建特殊窗体

目录 1.TreeView控件 2.实例 &#xff08;1&#xff09;Resources.Designer.cs &#xff08;2&#xff09;Form1.Designer.cs &#xff08;3&#xff09;Form1.cs &#xff08;4&#xff09;生成效果 以树形来显示程序的菜单&#xff0c;可以更直观、更快捷地对窗体进行…

科技赋能无人零售

科技赋能无人零售&#xff0c;使其具备以下独特优势&#xff1a; 1. 全天候无缝服务 &#xff1a;无人零售店依托科技&#xff0c;实现24小时不间断运营&#xff0c;不受人力限制&#xff0c;满足消费者随时购物需求&#xff0c;尤其惠及夜间工作者、夜猫子及急需购物者&…

Android --- 常见UI组件

TextView 文本视图 设置字体大小&#xff1a;android:textSize"20sp" 用sp 设置颜色&#xff1a;android:textColor"#00ffff" 设置倍距(行距)&#xff1a;android:lineSpacingMultiplier"2" 设置具体行距&#xff1a;android:lineSpacingExtra&q…

基于RK3588的全国产鸿蒙边缘计算工控机在智能交通ETC收费系统的应用

1.1 产品简介 基于智能交通、工业互联等行业快速智能化发展的需求&#xff0c;以 OpenHarmony 为框架开发嵌入 HamonyOS&#xff0c;打造了具有高智能、高可靠、高安全的自主 可控的边缘处理器 XM-RK3588。 图 1-1 边缘处理器 HamonyOS强化 IoT 互联互动能力&#xff0c;让边缘…

Python爬虫入门指南--爬虫技术的由来、发展与未来--实战课程大赠送

爬虫&#xff0c;也称为网络爬虫或网络蜘蛛&#xff0c;是一种自动化程序&#xff0c;专门用于遍历互联网并收集数据。这种技术的起源、发展和未来都与互联网紧密相连&#xff0c;并在信息检索、数据挖掘等多个领域发挥着不可或缺的作用。 "免费IP池大放送&#xff01;助…

堆的概念、堆的向下调整算法、堆的向上调整算法、堆的基本功能实现

目录 堆的介绍 堆的概念 堆的性质 堆的结构 堆的向下调整算法 基本思想&#xff08;以建小堆为例&#xff09; 代码 堆的向上调整算法 基本思想&#xff08;以建小堆为例&#xff09; 代码 堆功能的实现 堆的初始化 HeapInit 销毁堆 HeapDestroy 打印堆 HeapPrint …

洛谷 P1021 邮票面值设计

原题链接&#xff1a;[NOIP1999 提高组] 邮票面值设计 - 洛谷 目录 题目描述 解题思路&#xff1a; 代码实现&#xff1a; 题后总结&#xff1a; 题目描述 给定一个信封&#xff0c;最多只允许粘贴 N 张邮票&#xff0c;计算在给定 K&#xff08;NK≤15&#xff09;种邮票…

RAG的进化之路:从单兵作战到多智协作

原文&#xff1a;https://arxiv.org/pdf/2404.15155.pdf 近年来,随着大规模预训练语言模型的蓬勃发展,基于检索的知识问答技术越来越受到学术界和工业界的青睐。其中最具代表性的当属RAG方法。RAG通过将外部知识库集成到语言模型中,对输入的问题进行深入理解、推理,并生成相应的…

【C语言】联合体详解

目录 1.联合体的声明 2.联合体的特点 3.相同成员的结构体和联合体对比 4.联合体大小的计算 1.联合体的声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成&#xff0c;这些成员可以不同的类型。但是编译器只为最大的成员分配足够的内存空间。 联合体的特点是所…

骑砍2霸主MOD开发(6)-使用C#-Harmony修改本体游戏逻辑

一.C#-Harmony反射及动态注入 利用C#运行时环境的反射原理,实现对已加载DLL,未加载DLL中代码替换和前置后置插桩. C#依赖库下载地址:霸王•吕布 / CSharpHarmonyLib GitCodehttps://gitcode.net/qq_35829452/csharpharmonylib 根据实际运行.Net环境选择对应版本的0Harmony.dll…

C++(Qt)软件调试---crashpad捕获崩溃(19)

C(Qt)软件调试—crashpad捕获崩溃&#xff08;19&#xff09; 文章目录 C(Qt)软件调试---crashpad捕获崩溃&#xff08;19&#xff09;1、概述2、资源地址3、配置环境4、解决报错5、测试代码6、测试结果7、Qt中使用crashpad 更多精彩内容&#x1f449;个人内容分类汇总 &#x…

矩阵按列相乘运算的并行化实现方法

这两天一直在琢磨如下矩阵计算问题。 已知dm矩阵X和hq矩阵Y&#xff0c;求如下矩阵&#xff1a; 其中X(:,i), Y(:,j)分别表示矩阵X, Y的第i列和第j列&#xff0c;易知Z为dh矩阵。 如果直接串行计算矩阵Z&#xff0c;两个循环共有mq&#xff0c;则会很慢&#xff0c;能不能并行化…

枚举(enum)/共用体(union)/结构体(struct)---详解

前言 C语言包含内置类型和自定义类型。 其实C语言中有内置类型&#xff0c;包含&#xff1a;char,short,int,long,long long,float,double,long double ,这些是C语言本身支持的现成的类型。 但仅仅只有内置类型是远远不够的&#xff0c;在描述一个复杂对象是无法使用内置类型来…

区块链安全应用------压力测试

测试要求&#xff1a; 1. 对以下AccountManager智能合约进行压测(基础要求set函数测试&#xff0c;balanceOf涵为20分加分项)2. 在本地链进行测试&#xff0c;需要监控本地进程的资源使用情况。每个进程的multiOutput属性为Avg3. 需要将每一个更改的配置文件截图&#xff0c;和…

政安晨:【Keras机器学习示例演绎】(十五)—— 用于图像分类的 CutMix 数据增强技术

目录 简介 设置 加载 CIFAR-10 数据集 定义超参数 定义图像预处理函数 将数据转换为 TensorFlow 数据集对象 定义 CutMix 数据增强功能 可视化应用 CutMix 扩增后的新数据集 定义 ResNet-20 模型 使用经 CutMix 扩展的数据集训练模型 使用原始非增强数据集训练模型 …

vscode 配置verilog环境

一、常用的设置 1、语言设置 安装如下插件&#xff0c;然后在config 2、编码格式设置 解决中文注释乱码问题。vivado 默认是这个格式&#xff0c;这里也设置一样。 ctrl shift p 打开设置项 3、插件信任区设 打开一个verilog 文件&#xff0c;显示是纯本文&#xff0c;没…

Xbar控制图的定义和应用

1、定义 Xbar控制图&#xff08;X-Bar Chart&#xff09;是一种统计图表&#xff0c;用于展示数据分布情况。它通过绘制一系列数据点在均值线&#xff08;通常为X轴&#xff09;周围的分布情况来显示数据的波动性。这种图表可以用来监控生产过程、质量管理、金融分析等多个领域…

【MHA】MySQL高可用MHA介绍1-功能,架构,优势,案例

目录 一 MHA 介绍 1 MHA功能 自动化主服务器监控和故障转移 交互式&#xff08;手动启动的&#xff09;主故障转移 非交互式主故障转移 在线切换主机 2 主服务器故障转移的难点 二 MHA架构 1 MHA组件 2 自定义扩展&#xff08;脚本&#xff09; 三 MHA优势 1 MHA可以…