在寻找最短路径时,BFS 和 Dijkstra 的算法有啥区别?
Posted
技术标签:
【中文标题】在寻找最短路径时,BFS 和 Dijkstra 的算法有啥区别?【英文标题】:What is difference between BFS and Dijkstra's algorithms when looking for shortest path?在寻找最短路径时,BFS 和 Dijkstra 的算法有什么区别? 【发布时间】:2014-10-16 11:18:11 【问题描述】:我正在阅读图算法,我遇到了这两种算法:
Dijkstra's algorithm Breadth-first search在寻找节点间最短路径时,Dijkstra 算法和 BFS 有什么区别?
我对此进行了很多搜索,但没有得到任何满意的答案!
BFS 在图中寻找最短路径的规则是:
-
我们发现所有连接的顶点,
将它们添加到队列中,然后
存储从源 u 到该顶点 v 的距离(重量/长度)。
更新从源 u 到距离最短的顶点 v 的路径,我们就有了!
这与我们在 Dijkstra 算法中所做的完全一样!
那么为什么这些算法的时间复杂度如此不同?
如果有人可以借助伪代码来解释它,那么我会 非常感谢!
我知道我错过了什么!请帮忙!
【问题讨论】:
你看过***吗? “广度优先搜索可以看作是 Dijkstra 算法在未加权图上的一个特例,其中优先级队列退化为 FIFO 队列。” 是的!我也在 *** 上阅读了几乎所有与此相关的问题,但没有得到正确的答案! Why use Dijkstra's Algorithm if Breadth First Search (BFS) can do the same thing faster?的可能重复 【参考方案1】:当使用 BFS 在图中查找最短路径时,我们会发现所有连接的顶点,将它们添加到队列中,并保持从源到该顶点的距离。现在,如果我们找到从源到那个顶点的距离更短的路径,那么我们就更新它!
我们在 BFS 中不保持距离。它用于发现节点。 所以我们把它们放在一个通用队列中并弹出它们。与 Dijikstra 不同,我们将节点的累积权重(松弛后)放入优先级队列并弹出最小距离。
所以 BFS 在等权图中会像 Dijikstra 一样工作。由于使用简单队列和优先级队列,复杂性会有所不同。
【讨论】:
【参考方案2】:Dijkstra 和 BFS,都是同一个算法。正如其他成员所说,Dijkstra 使用 priority_queue 而 BFS 使用队列。不同之处在于两种算法中最短路径的计算方式。
在 BFS 算法中,为了找到最短路径,我们在各个方向上遍历并分别更新距离数组。基本上,伪代码如下:
distance[src] = 0;
q.push(src);
while(queue not empty)
pop the node at front (say u)
for all its adjacent (say v)
if dist[u] + weight < dist[v]
update distance of v
push v into queue
上面的代码也会给出加权图中的最短路径。但是时间复杂度不等于正常的 BFS,即 O(E+V)。时间复杂度超过 O(E+V),因为许多边重复了两次。
Graph-Diagram
考虑一下上图。对上面的伪代码进行空运行,你会发现节点 2 和节点 3 被两次推送到队列中,并且所有未来节点的距离都更新了两次。
BFS-Traversal-Working
因此,假设如果在 3 之后有更多节点,那么通过第一次插入 2 计算的距离将用于所有未来的节点,那么这些距离将使用节点 2 的第二次推送再次更新。与 3 相同的场景. 因此,您可以看到节点是重复的。因此,所有节点和边都不会只遍历一次。
Dijkstra 算法在这里做了一个聪明的工作......而不是在所有方向上遍历它只在最短距离的方向上遍历,这样可以防止重复更新距离。 因此,为了追踪最短距离,我们必须使用 priority_queue 代替普通队列。
Dijkstra-Algo-Working
如果您尝试使用 Dijkstra 算法再次空运行上图,您会发现节点被推送两次,但只考虑距离较短的节点。
因此,所有节点都只遍历一次,但由于使用了priority_queue,时间复杂度高于普通BFS。
【讨论】:
【参考方案3】:使用SPFA algorithm,可以得到加权边图中正常队列的最短路径。
它是bellman-ford algorithm的变体,也可以处理负权重。
但不利的一面是,它比 Dijkstra 的时间复杂度更差
【讨论】:
【参考方案4】:广度优先搜索就是 Dijkstra 的算法,所有边的权重都等于 1。
Dijkstra 的算法在概念上是尊重边成本的广度优先搜索。
在这两种情况下,探索图的过程在结构上是相同的。
【讨论】:
那为什么时间复杂度有区别呢?我的意思是为什么他们说在非加权图中寻找最短路径时使用 BFS 而不是 Dijkstra 的? @harrythomas Dijkstra 使用优先级队列数据结构来跟踪未访问节点的边界。广度优先搜索使用常规队列数据结构。优先级队列上的操作是 O(log n)。常规队列上的操作是 O(1)。所有边权重都为 1 使得在 BFS 中使用常规队列成为可能 - 这使得常规队列有效地表现为优先级队列。以上是关于在寻找最短路径时,BFS 和 Dijkstra 的算法有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章