核心对比
| 算法 | 主要用途 | 适用情况 | 不适用情况 | 时间复杂度 |
|---|---|---|---|---|
| BFS | 无权图的单源最短路径 | 无权图、等权图 | 一般带权图 | 邻接表:;邻接矩阵: |
| Dijkstra | 非负权图的单源最短路径 | 所有边权 | 有负权边 | 邻接矩阵:;堆优化: |
| Floyd | 所有顶点对之间的最短路径 | 可有负权边,但不能有负权回路 | 负权回路 |
其中, 表示顶点数, 表示边数。
BFS
适用范围
BFS 最适合求解无权图的单源最短路径。
B
/ \
A -- D
\ /
C
从 出发时,BFS 会逐层搜索:
因为无权图默认每条边的长度都是 ,所以:
如果各边权值分别为 等不同数值,一般不能使用 BFS 求最短路径。
时间复杂度
使用邻接表时,每个顶点最多访问一次,每条边最多检查一次或两次,因此:
使用邻接矩阵时,需要扫描矩阵中的顶点关系,时间复杂度为 。
Dijkstra
适用范围
Dijkstra 最适合求解非负权图的单源最短路径。例如从 出发:
A --2-- B
| |
5 1
| |
C --1-- D
它可以分别求出 、 和 的最短距离。
重要限制
重点: Dijkstra 不能处理负权边。
例如:
由于存在权值为 的边,Dijkstra 的贪心策略可能失效。因此,考试中看到“Dijkstra 可以处理负权边”,通常应判断为错误。
时间复杂度
- 邻接矩阵实现: 每轮都要从尚未确定的顶点中寻找最小距离,共进行 轮,时间复杂度为 。
- 邻接表与最小堆实现: 时间复杂度为 ,很多资料也简写为 。
在数据结构考试中,如果题目没有特别说明使用堆优化,通常采用传统实现的 。
Floyd
适用范围
BFS 和 Dijkstra 通常解决的是从一个起点到其他所有顶点的最短路径,而 Floyd 解决的是任意两个顶点之间的最短路径,也称为多源最短路径或全源最短路径。
假设图中有 四个顶点,Floyd 一次运行后,不仅能得到 到其他顶点的距离,还能得到 、、 到其他顶点的距离,最终形成完整的距离矩阵。
Floyd 可以处理负权边,但不能存在负权回路。若回路 的总权值为 ,反复经过该回路会使路径长度变为 ,因此不存在正常意义上的最短路径。
时间复杂度
Floyd 的核心是三重循环,不断更新:
三个循环都最多执行 次,因此:
如何选择
| 需求 | 首先想到 |
|---|---|
| 无权图的单源最短路径 | BFS |
| 非负权图的单源最短路径 | Dijkstra |
| 任意两点之间的最短路径 | Floyd |
| 图中存在负权边 | Dijkstra 不适用;可以考虑 Floyd |
| 图中存在负权回路 | 一般不存在正常意义上的最短路径 |
其中,“单源”指从一个指定顶点出发,“全源”指求任意两个顶点之间的最短路径。
记忆: BFS——无权单源;Dijkstra——非负权单源;Floyd——全源最短路,可有负权边但不能有负权回路。