在寻找最短路径时,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 的算法有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

最短路径之Dijkstra算法和Floyd-Warshall算法

Dijkstra算法(转)

最短路径 Dijkstra 算法为啥边上的权值非负阿?

搜索带权图最短路径的Dijkstra算法

最短路径

Dijkstra算法