BFS宽搜和DFS深搜小结

C++ 算法篇 广度(宽度)优先搜索(BFS) 广度优先遍历 广度优先遍历(Breadth_First_Search),又称为广度优先搜索,简称BFS。 图的BFS类似于树的层序遍历。 广度优先遍历 如图将左边的图变形,得到右边的图,然后一层一层的遍历。 这里借助一个队列来实现一层一层的遍历。 邻接矩阵的BFS 核心代码 /** * 邻接矩阵的广度优先遍历算法 */ void BFSTraverse(MGraph G){... 阅读详情

什么时候需要用到BFS呢?通常图的遍历(Traversal in Graph)
主要有以下四种情况:

  1. 层级遍历 - Level Order Traversal
    最经典的就是二叉树的level order traversal
  2. 由点及面 Connected Component
    即由一个点,找出图中所有的点。比如给出无向连通图(Undirected Connected Graph)中的一个点,找到这个图里的所有点。
  3. 拓扑排序 Topological Sorting
    拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面。注意这里一定是有向图。
    注意:
    3.1 一个有向图的拓扑排序可能存在多个,通常的拓扑排序程序只需要输出一个即可。
    3.2 注意一个有向图的拓扑排序也可能不存在,一个有向图的拓扑排序的充要条件就是存在环。
    3.3 拓扑排序也可以用DFS,但不如BFS简单。
    3.4 找有向图的环也可以用Tarjan算法。
  4. 简单图的最短路径 Shortest Path in Simple Graph
    注意这里一定要是简单图,也就是图中每条边长度都是1(或边长都相同)。为什么呢? 因为宽搜可以理解为一层层进行的,就跟二叉树遍历一样。要是层和层之间,或每层的长度都不一样,宽搜就没法进行了。通常这里简单图求最短路径用到BFS的都是无向图,极少数是有向图。注意:
    4.1 求最短路径也可以用DP,Dijkstra, Bellman-Ford算法等。
    4.2 BFS不能用来求简单图的最长路径。Dijkstra也不能求最长路径。Bellman-Ford算法可以求最长路径,有环也可以,只要把图中的边权改为原来的相反数即可。也可以用Floyd-Warshall求最长路径,但不能有环(Floyd算法的本质是DP)。
    4.3 BFS对无向图和有向图都适用。
    4.4 二叉树中进行 BFS 和图中进行 BFS 最大的区别就是二叉树中无需使用 HashSet或HashMap来存储访问过的节点(丢进过 queue 里的节点)
    因为二叉树这种数据结构没有环,不可能出现一个节点的儿子的儿子是自己的情况。但是在图中,一个节点的邻居的邻居就可能是自己了。

另外,BFS还有双向BFS, DFS却没有双向DFS。双向BFS适用于如下场景:

  1. 无向图
  2. 所有边的长度都为 1 或者长度都一样
  3. 同时给出了起点和终点
    以上 3 个条件都满足的时候,可以使用双向宽度优先搜索来求出起点和终点的最短距离。

什么是用到DFS呢?

  1. 找所有解/方案(或者所有组合,全部路径之类)的题,基本上都可以用DFS。当然有些用BFS也可以做。
  2. 求最长路径也可以用DFS。

注意:

  1. DP不能用来求所有解,而只能求所有解的个数。另外,DP 也用来求最优解,比如说最短路径(BFS也可以)。但DP可以求最长路径但BFS不可以。
  2. DFS的题目除了二叉树以外,90%都是排列组合题。
  3. DFS如果迭代层数太深,会有stack overflow问题 。但是对于二叉树和排列组合之类的问题用DFS一般不会有stack overflow。二叉树的迭代深度平均O(logn),最差O(n)。排列组合的迭代深度最多是O(n),而n一般不会很,比较典型的是20,30左右。
    4)关于BFS和DFS的时间复杂度
    DFS搜索的时间复杂度是O(答案个数*构造每个答案时间),或者说是O(解的个数 * 产生解的复杂度)。所以subsets的时间复杂度是O(n*2^n), permutation的时间复杂度是O(n*n!)。

我们以subsets举例 (引用自九章):
搜索时间复杂度公式:O(解的个数 * 产生解的复杂度), 因为解的平均长度是n/2,所以扩2倍也没有关系,可以认为是n的。 实际复杂度是O(2^n * n / 2) = O(2^(n-1) * n), 这是根据公式估算的。具体来看这个复杂度用数学推到如何算出来;

严格意义上来讲是复杂度是这样的:
**1 * 长度为1的解的个数 + 2 * 长度为2的解的个数 + 3 * 长度为3的解的个数 + n * 长度为n的解的个数 = **
1 * c(n, 1) + 2 * c(n, 2) + … + n * c(n,n)
// c(m,n) 是排列组合中的组合

又因为
i * C(n, i) = i * n! / [i! (n-i)!] = n! / [(i-1)! (n-i)!] = n * (n-1)! / [(i-1)! (n-i)!] = n * C(n-1,i-1)

所以
**1 * c(n, 1) + 2 * c(n, 2) + … + n * c(n,n) = sum(i * c(n, i)) = sum(n * c(n - 1, i - 1)) = n * sum(c(n-1, i-1)) **
其中 1 <= i <=n

sum(c(n - 1, i - 1)) 就是杨辉三角的某一层的求和 ,为2^(n - 1)

最后得出:1 * c(n, 1) + 2 * c(n, 2) + … + n * c(n,n) = 2^(n - 1) * n

跟我们的估算完全一致。有时候不需要数学推导,因为是大O,又是搜索算法,故用我们的公式估计一个大概就可以了。

permutations 可以用类似的方式推导。

注意这里是搜索的时间复杂度估计的公式,并不是特别指DFS的,BFS也适合。

对于BFS,因为每个点进入queue一次,加上每个点出来时候处理的复杂度,可以认为是O(点的个数 * 每个点处理的平均复杂度)

再对比一下DP。DP的时间复杂度是O(状态总数×计算每个状态时间复杂度)。

5) 关于BFS和DFS的空间复杂度
BFS的空间复杂度是同一层的最大宽度(最坏情况所有点都在一层,所以是O(n))。
DFS的空间复杂度取决于深度,一般堆和栈都要计算在内。但有时人们认为系统栈很小,所以只算堆空间。
对于排列组合问题的空间复杂度来说,一般DFS优于BFS。因为排列的所有解个数是O(n!),组合的所有解个数是O(2^n) 。
而DFS递归的深度是O(n),即DFS的空间复杂度是O(n)。而BFS对排列最坏空间复杂度是排列O(n!),对组合的最坏空间复杂度是O(2^n)。

下面内容引用自
https://blog.youkuaiyun.com/Charles_ke/article/details/82497543
v为图的顶点数,E为边数。
BFS的复杂度分析:
BFS是一种借用队列来存储的过程,分层查找,优先考虑距离出发点近的点。无论是在邻接表还是邻接矩阵中存储,都需要借助一个辅助队列,v个顶点均需入队,最坏的情况下,空间复杂度为O(v)。
邻接表形式存储时,每个顶点均需搜索一次,时间复杂度T1=O(v),从一个顶点开始搜索时,开始搜索,访问未被访问过的节点。最坏的情况下,每个顶点至少访问一次,每条边至少访问1次,这是因为在搜索的过程中,若某结点向下搜索时,其子结点都访问过了,这时候就会回退,故时间复 杂度为O(E),算法总的时间复 度为O(|V|+|E|)。

邻接矩阵存储方式时,查找每个顶点的邻接点所需时间为O(V),即该节点所在的该行该列。又有n个顶点,故算总的时间复杂度为O(|V|^2)。

DFS复杂度分析
DFS算法是一一个递归算法,需要借助一个递归工作栈,故它的空问复杂度为O(V)。

遍历图的过程实质上是对每个顶点查找其邻接点的过程,其耗费的时间取决于所采用结构。

邻接表表示时,查找所有顶点的邻接点所需时间为O(E),访问顶点的邻接点所花时间为O(V),此时,总的时间复杂度为O(V+E)。

邻接矩阵表示时,查找每个顶点的邻接点所需时间为O(V),要查找整个矩阵,故总的时间度为O(V^2)。

c++宽度优先搜索BFS 宽度优先搜索,又叫做广度优先搜索,简称宽搜(BFS),是另一种常见搜索算法(还有一种是深搜)。宽搜是一种图的搜索算法,运用非常广泛,也很基础,是每一个编程者必学的算法。因为它是一个很便捷的算法,可拓展性也很高。一些图的最短路算法基本上都是用的是宽搜,或者是基于宽搜。比如Dijstra(求单源最短路径的),和Prim(最小生成树)。这两个都是比较进阶一点的算法,只有把宽搜学扎实了,才有拓展的可能。总之,宽搜必学! 阅读详情

相关推荐

【算法学习】DFS与BFS

从A开始遍历,再到B,有两种情况,意味着这条路还没有走完,接着走到D,之后就没路了。然后我就回溯到B,因为B还有情况没走完,接着再走到E,之后没路了,就回溯到B,发现B的两种情况以及那个走完了,就再回溯到A,然后走到C......最初,有一个人位于左上角(1,1)处,已知改人每次可以向上,下,做,右任意一个方向移动一个位置。给的那个一个n*m的二维整数数组,用来表示迷宫,数组中只包含1和0,0表示可以走的路,1表示不可以通过的墙壁。简单理解就是:一条路走动黑,直到没路可走了,再回溯回去,尝试其他路径。

2401_82677021的博客 3393

宽度优先搜索算法(BFS)详解(超级详细讲解,附有大图)

​ 补充说明:由上可以知道,广度优先搜索的特征为从起点开始,由近及远进行广泛的搜索。因此,目标顶点离起点越近,搜索结束得就越快。 三.对比与发现 DFS和BFS的区别 bfs 遍历节点是先进先出,dfs遍历节点是先进后出; bfs是按层次访问的,dfs 是按照一个路径一直访问到底,当前节点没有未访问的邻居节点时,然后回溯到上一个节点,不断的尝试,直到访问到目标节点或所有节点都已访问。 bfs 适用于求源点与目标节点距离最近的情况,例如:求最短路径。dfs 更适合于求解一个任意符合方案中的一个或者遍历所有情

aliyonghang的博客 5万+

图的遍历-----深度优先遍历(dfs),广度优先遍历(bfs)【java详解】

图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历。遍历过程中得到的顶点序列称为图遍历序列。深度优先搜索(DFS,Depth First Search)广度优先搜索(BFS,Breadth First Search)

2302_79862386的博客 3826

2021-08-08

宽搜的概念 文章目录宽搜的概念枚举搜索前提条件定义宽搜的实现宽度优先搜索的基本框架输出数据输出格式 枚举搜索 把待搜索的空间划分成若干个区域,要求划分的区域不重复,不遗漏。 按照一定的顺序逐一搜索每个区域,直至找到目标或者整个空间搜索完毕。 前提条件 能够清楚地知道整个空间的大小。 划分的区域是能够按照一定的顺序去搜索的。 定义 宽度优先搜索(Breadth First Search, BFS)又称为广度优先搜索。 宽度优先搜索算法属于一种盲目搜索,目的是从起始结点出发,系统地展开状态空间中的所

Black_Capsule的博客 388

深度优先搜索之记忆化dfs

文章目录前言朴素dfs的求解思路记忆化dfs的求解思路将整数按权重排序题目描述解题思路朴素dfs记忆化dfs小结矩阵中的最长递增路径题目描述解题思路朴素dfs记忆化dfs小结统计所有可行路径题目描述解题思路朴素dfs记忆化dfs小结学生出勤记录 II题目描述朴素dfs记忆化dfs小结“马”在棋盘上的概率题目描述记忆化dfs骑士拨号器题目描述记忆化dfs记忆化dfs与棋结语 前言 前不久,我写一篇bfs的进阶版双向bfs:广度优先搜索之双向bfs 这篇文章主要是讲述对于一些特定的bfs问题,可以使用两头齐搜的

Rookie 4193

【人工智能】— 深度优先搜索、代价一致搜索、深度有限搜索、迭代深度优先搜索、图搜索

搜索问题是指既不能通过数学建模解决,又没有其他算法可以套用或者非遍历所有情况才能得出正确结果。这时就需要采用搜索算法来解决问题。搜索就是一种通过穷举所有解的状态,来求得题目所要求的解或者最优解的方法。搜索的基本概念:状态:对某一系统在某一时刻的数学描述。动作:从当前时刻状态转移到下一时刻所处状态的操作。状态转移:对某一时刻的状态进行动作后所达到的状态。路径:一个状态序列,该序列被一系列动作所连接。目标测试:评估当前状态是否是所求解的目标状态。

我们都是被分成两半的人,一边热爱生活,一边憎恨生活。面对生活,我们总是在矛盾的两端摇摆,在反复的矛盾和犹豫中,一边踉跄前行,一边重振旗鼓。我渴望改变,渴望变得更好,渴望找到出口……就像一个溺水人的挣扎,就像一个救生圈。我是一个矛盾集合体,想要变得快乐,但是 6752

算法——队列+宽搜(BFS)

队列这种数据结构大都服务于一个算法——宽搜(BFS)。宽搜还可以运用到二叉树、图、迷宫最短路径问题、拓扑排序等等。

裙下的霸气的博客 1071

深度学习(Deep Learning, DL)简介

深度学习(Deep Learning, DL)是机器学习的一个子领域,主要使用多层神经网络来处理复杂的数据和任务。深度学习通过模拟人脑的神经网络结构,能够自动提取特征并进行高效的模式识别和预测。

qq_28791753的博客 1万+

DFS和BFS

BFS是一种基于队列的遍历算法,适合解决最短路径、层次遍历等问题。注意访问标记和队列的使用,避免重复访问和无限循环。根据具体问题选择合适的变种或优化方法。

2401_88817961的博客 921

红外图像处理实战:用MATLAB实现时域高通滤波(THPF)去噪(附完整代码)

本文详细介绍了如何利用MATLAB实现时域高通滤波(THPF)算法进行红外图像去噪,包括核心原理、工程实现要点和完整代码示例。通过分析时间窗口选择、空域预处理优化和自适应参数调整等关键点,帮助开发者有效抑制固定图案噪声,适用于无人机载红外监测和安防监控等场景。

weixin_42783709的博客 183

易灵思Ti60F100 FPGA的HyperRAM实战:从硬件连接到Native接口时序调试

本文详细介绍了易灵思Ti60F100 FPGA内置HyperRAM控制器的实战应用。文章从硬件设计要点(如400MHz+信号完整性、等长匹配)切入,重点解析了如何通过Interface Designer配置高效的Native接口,并分享了其时序详解与调试技巧,为开发者提供了一份从硬件连接到软件调试的深度指南。

weixin_29168153的博客 454

【算法合集】深搜广搜Prim与Kruskal

广度优先搜索(BFS)又叫广搜,它像一个有远见的人,它是一层一层来实现搜索的,也挺像下楼梯的。 思路: 1.先初始化队列 q; 2.从起点开始访问,并且改变他的状态为已经访问; 3.如果他的队列非空,取出首个元素,将它弹出! 4.如果u == 目标状态,然后对所以与 u 邻近的点进入队列; 5.标记它已经被访问!...............

程序猿追的博客 2万+

主成分分析避坑指南:为什么你的PCA结果总是不理想?

本文深入剖析了主成分分析(PCA)在实际应用中效果不佳的常见原因与解决方案。针对数据标准化、协方差矩阵选择、主成分数量确定、载荷矩阵解读等关键环节,提供了详细的避坑指南和诊断方法,并探讨了PCA的局限性及非线性数据结构下的备选方案,帮助数据分析师获得更稳健、可解释的降维结果。

convnet3designer的博客 510

深搜+回溯+广搜小结

深搜 按照一定的顺序和规则,一直往深处走,直到走不通再返回,换一种路径重复上述步骤。 深搜一般可以找到问题的所有答案,但问题规模较大时,会产生很多结果,时间复杂度就会较高。与广搜相比,深搜的空间复杂度会较低,因为深搜是深度优先,不需要像广搜那样存储大量状态。 优化 1、可行性剪枝和最优性剪枝 2、记忆化搜索 3、减少重复搜索 问题练习 P1451 求细胞数量 深搜的入门题,求出连通块,把搜索过的地方做标记,记录连通块数量即可 #include <bits/stdc++.h> #define ep

BOSS站着我躺着 1492

记一次Nacos线程数飙升排查

Nacos线程飙升问题排查

叭嘣的博客 2631

从符号到基元:Token的技术演化史与“词元”汉化的术语学

中文摘要:Token概念演化与"词元"译名的确立 本文系统梳理了"Token"概念从信息论符号到AI基元的完整演化史,揭示了"词元"这一中文译名确立的必然性。概念发展经历了三个阶段:早期作为编译原理中的词法单元(1960s),统计NLP时期作为概率空间的原子(1990s-2000s),以及神经时代成为动态语义载体(2010s后)。随着Transformer架构兴起,Token从静态符号转变为上下文相关的语义基元,其定义彻底突破"词&quo

AllenLV的博客 1220

小结:A* & IDA* & 迭代深搜

概要: 在dfs中,如果答案的深度很小但是却很宽,而且bfs还不一定好做的情况下,我们就综合bfs的优点,结合dfs的思想,进行有限制的dfs。在这里A*、IDA*和迭代深搜都是对dfs的优化,因此放到一块小结。 A*的概念主意在于估计函数,f(n)=g(n)+h(n),f(n)是估计函数,g(n)是n节点的当前代价,h(n)是n节点的估计代价;而实际中,存在最优的估计函数f'(n)...

126

C# 从数秒到毫秒:MySQL+Redis百万数据优化实战全解析

在处理百万级数据时,传统单体数据库常面临查询效率低下、数据库负载过高和用户体验差等问题。为解决这些性能瓶颈,可以采用MySQL分库分表、Redis缓存和异步统计的组合策略。 数据库分片:通过水平分表和分库实现,将单表数据分散到多个物理表或数据库实例中,降低单点负载。 Redis缓存:利用Redis缓存高频数据,减少数据库查询压力,提升响应速度。 异步统计:通过消息队列(如RabbitMQ)解耦统计任务,后台处理非实时任务,避免阻塞主流程。 这些优化策略能够显著提升系统性能,确保在高并发和大数据量场景下的稳定

墨夶的博客 852

dfs、bfs搜索题型小结

最短路问题,一般采用bfs比较好;想用dfs解决的话,需要剪枝;下面这几道涉及到状态压缩,比普通的题会稍微复杂一点;求连通块数量,可以顺便求一下连通块中的最大数量;求连通块数量(此题默认只有两个),连通两个连通块。当然求连通块也可以用并查集来做,下面提供一个例题。这里用dfs解决,下面有一个bfs解决方法;这种问题就不需要回溯;

与其邻渊羡渔,不如退而结网 1325

【AI理论学习】手把手推导扩散模型:Diffusion Models(DDPM)

生成扩散模型DDPM如下图所示分为前向、逆向两个过程,它首先通过不断往原始清晰数据中添加噪声使其变成标准高斯噪声(前向过程),而后期望从标准高斯噪声中还原原始数据(逆向过程)。若能实现,那便可从已知的标准高斯分布中采样一个噪声数据,而后利用DDPM模型生成符合原始数据分布的新数据。 Diffusion模型包含两个过程:数学符号:y∝xy\propto xy∝x:y正比于x,即y随着x增大而线性增大。 条件概率:贝叶斯公式:p(A∣B)=p(B∣A)×p(A)p(B)p(A|B)=\frac{p(B|A)\

小哲的博客 1509

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

关于DFS和BFS这个算法

广度优先算法(Breadth-First-Search),简称BFS。从知识点看属于图结构的搜索算法,是一种相对容易理解的简单算法。BFS算法从问题的初始状态(起点)出发,根据状态转换规则(图结构中的边),遍历所有可能的状态(其他节点),直到找到终结状态(终点)。因此BFS算法的复杂度和状态集合的总数密切相关。BFS算法虽然出自图结构,但其常用的领域却不是解决图论相关问题。

qq_73261465的博客 477

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

【BFS && DFS】模块小结

BFS 模板(后面有单独的bfs小结)写 一下做BFS 的思路。因为这题比较简单,代码量相对较少,也容易理解一些 更容易总结出模板1、先定义有关变量,一般是一个边界值、一个初始值、一个标记数组、加上一个 数组(一个变量) pair<>类型 (两个变量,如 x,y 坐标类型) 或 struct 定义一个新的类(三个以上变量)2.按照题意先建立主函数,如果是迷宫类问题,读入的可以直接用一层for循环加

Nodies 693

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

宽搜总结——BFS

开始练习了BFS,这是原来一直不太会用的东西。(几乎学过后就没用过……)心得如下: 与DFS相比,宽搜去掉了递归调用的层次,而是改用队列来严格得维护处理数据时的先后顺序。它的原理是在找到一个节点ai时(老师:“这里必须先判断ai是否已经进队!”)直接将ai的所有子节点全部进队,然后再回到找到节点ai的层数中找下一个可以拓展子节点的节点。。。因为用的是队列而不是递归,这样也可以自己控制队的大小而不会

384

DFS与BFS小结

DFS!!! 1、2020蓝桥杯决赛A组E题《玩具蛇》 难度:** 题意 :在4*4矩阵中放入1-16号数字,使得连续的数字相邻,则放法有多少种(设每个格子均不同) 思路:1个1个放,上下左右探索。巩固深搜语法——visit置1,搜索下一层,visit置0。 int visit[4][4],cnt=0; //设置是否经过,计数 int x[4]={-1,0,1,0},y[4]={0,-1,0,1}; //探索方向 void init(){ //重新开始的初始化函数 for (int i=0;i

qq_45677735的博客 411

dfs bfs java_DFS和BFS讲解及Leetcode刷题小结(1)(JAVA)

DFS(深度优先)与BFS(广度优先)是两种非常重要的算法,要注意的是,这是算法,与其数据结构并无关系,任何数据结构都可以使用这种算法!其中树和图的数据结构使用该算法比较多。这两种算法原理非常好理解,但是他们的应用极其的灵活,而且实现步骤上极其讲究,非常容易编写错误,但又找不到问题的出处,希望这两篇文章可以从原理到实现,从实现到应用完整的讲解DFS与BFS这篇文章为对DFS的整理,文末为Leetc...

weixin_39669163的博客 298
上一篇: LintCode-127: Topological Soring 拓扑排序 (经典题)
下一篇: LintCode-615: Course Schedule and Course Schedule II 拓扑排序经典题
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值