FC09-Dijkstra算法:求有向图or无向图中从源点到其他各顶点的最短路径¶
代码实现¶
代码逻辑解析¶
1. Dijkstra算法基本思想¶
- 从源点开始,逐步确定到各顶点的最短路径
- 每次选择当前距离源点最近的未确定顶点
- 通过该顶点更新其他顶点的最短距离
- 重复此过程直到所有顶点的最短路径都确定
2. 关键数据结构¶
- visit数组:标记顶点是否已确定最短路径
- lowcost数组:记录源点到各顶点的当前最短距离
- parent数组:记录最短路径中各顶点的前驱节点(用于路径重构)
3. 算法步骤详解¶
步骤1:初始化¶
| C | |
|---|---|
步骤2:主循环(执行n-1次)¶
步骤3:选择最近顶点¶
| C | |
|---|---|
步骤4:更新距离¶
| C | |
|---|---|
步骤5:路径输出¶
时间复杂度分析¶
1. 外层循环¶
- 执行
G.numver - 1次,即 O(V) 次
2. 内层循环¶
- 找最小顶点:O(V) 时间
- 更新距离:O(V) 时间
3. 路径输出¶
- 每个顶点的路径输出:O(V) 时间
- 总共 V 个顶点:O(V²) 时间
4. 总体时间复杂度¶
- O(V) × [O(V) + O(V)] + O(V²) = O(V²)
- 其中 V 是顶点数
5. 优化可能性¶
- 使用优先队列(最小堆)可以优化到 O((V + E) log V)
- 使用斐波那契堆可以优化到 O(V log V + E)
空间复杂度分析¶
1. 额外数组空间¶
visit[]:O(V)lowcost[]:O(V)parent[]:O(V)st[]:O(V)
2. 局部变量¶
- 常量级别的额外空间
3. 总体空间复杂度¶
O(V),其中 V 是顶点数
较难理解部分的说明¶
1. 松弛操作的理解¶
2. 路径重构过程¶
| C | |
|---|---|
3. 图解说明¶
假设有向图如下:
邻接矩阵表示:
| Text Only | |
|---|---|
Dijkstra算法执行过程(从顶点0开始):
最终结果: - 0到0:路径0,距离0 - 0到1:路径0→1,距离2 - 0到2:路径0→1→2,距离5 - 0到3:路径0→3,距离6
延伸知识点¶
1. 与Prim算法的对比¶
| 特性 | Dijkstra算法 | Prim算法 |
|---|---|---|
| 目的 | 单源最短路径 | 最小生成树 |
| 更新规则 | dist[j] > edge[pos][j] + dist[pos] |
dist[j] > edge[pos][j] |
| 初始值 | 源点为0,其他为∞ | 起始点为0,其他为∞ |
| 结果 | 树形结构(从源点出发的最短路径树) | 树形结构(连接所有顶点的最小权树) |
2. 优化版本 - 使用优先队列¶
3. 限制条件和扩展¶
Dijkstra算法的限制:¶
- 不能处理负权边:贪心策略在负权边情况下不成立
- 适用于非负权图:所有边权必须非负
处理负权边的算法:¶
4. 实际应用场景¶
- 导航系统:GPS路径规划,寻找最短行驶路线
- 网络路由:互联网数据包传输的最短路径选择
- 社交网络:寻找两个人之间的最短关系链
- 游戏开发:AI寻路算法,NPC移动路径规划
- 物流配送:快递配送的最优路线规划
- 电路设计:电子信号传输的最短延迟路径
5. 算法变体和扩展¶
Dijkstra算法体现了贪心策略在图论中的经典应用,通过局部最优选择达到全局最优解,是计算机科学中最重要的图算法之一。其核心思想是逐步扩展已知最短路径的顶点集合,直到所有顶点的最短路径都确定为止。