数据结构—— 图:最短路径问题
Posted 大彤小忆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构—— 图:最短路径问题相关的知识,希望对你有一定的参考价值。
3. 最短路径问题
3.1 最短路径问题的抽象
在网络中,求两个不同顶点之间的所有路径中,边的权值之和最小的那一条路径:
⋄
\\diamond
⋄ 这条路径就是两点之间的最短路径(shortestPath)
⋄
\\diamond
⋄ 第一个顶点为源点(Source)
⋄
\\diamond
⋄ 最后一个顶点为终点(Destination)
3.2 问题分类
单源最短路径问题: 从某固定源点出发,求其到所有其他顶点的最短路径。
⋄
\\diamond
⋄ (有向)无权图
⋄
\\diamond
⋄ (有向)有权图
多源最短路径问题: 求任意两顶点间的最短路径。
3.3 单源最短路算法
3.3.1 无权图的单源最短路算法
按照递增(非递减)的顺序找出各个顶点的最短路。
在数据结构(四)图 —— 编程作业 02 :Saving James Bond中,James Bond从孤岛跳上岸,最少需要跳多少步?
可以使用BFS算法计算!
BFS算法的代码如下所示。
void BFS(Vertex S)
{
visited[S] = true ;
Enqueue (S, Q);
while(!IsEmpty(Q)){
V = Dequeue (Q);
for (V的每个邻接点W)
if (!visited[W]){
visited[W] = true;
Enqueue (W, Q);
}
}
}
dist[W] = S到W的最短距离
dist[S] = 0
path[W] = S到W的路上经过的某顶点
无权图的单源最短路算法的代码如下所示。
void Unweighted(Vertex S){
Enqueue (S, Q);
while(!IsEmpty(Q)){
V = Dequeue (Q);
for(V的每个临界点W)
if (dist[W] == -1){
dist[W] = dist[V] + 1; // 当前距离上一距离+1
path[W] = V; // S到W的必经顶点就是前一个顶点V
Enqueue (W, Q);
}
}
}
时间复杂度为 T = O ( ∣ V ∣ + ∣ E ∣ ) T=O(|V|+|E|) T=O(∣V∣+∣E∣)。
3.3.2 有权图的单源最短路算法
按照递增的顺序找出各个顶点的最短路。
Dijkstra算法: 1. 令S={源点s +已经确定了最短路径的顶点
v
i
v_{i}
vi};
2. 对任一未收录的顶点v,定义dist[v]为s到v的最短路径长度,但该路径仅经过S中的顶点。即路径{ s→(
v
i
∈
S
v_{i}∈S
vi∈S)→v }的最小长度;
3. 若路径是按照递增(非递减)的顺序生成的,则
⋄
\\diamond
⋄ 真正的最短路必须只经过S中的顶点(为什么?)
⋄
\\diamond
⋄ 每次从未收录的顶点中选一个dist最小的收录(贪心)
⋄
\\diamond
⋄ 增加一个v进入S,可能影响另外一个w的dist值!
∘
\\circ
∘ dist[w] = min{dist[w], dist[v] +<v ,w>的权重}
有权图的单源最短路算法的代码如下所示。
void Dijkstra(Vrtex s)
{
while (1){
V = 未收录顶点中dist最小者;
if (这样的V不存在)
break;
collected[V] == true;
for (V的每个邻接点W)
if (collected[W]== false)
if (dist[V]+E<v,w> < dist[W])
{
dist[W] = dist[V]+ E<v,w>;
path[W] = V;
}
}
}
/*不能解决有负边的情况*/
■ 方法1: 直接扫描所有未收录顶点——
O
(
∣
V
∣
)
O(|V|)
O(∣V∣)
⋆
\\star
⋆
T
=
O
(
∣
V
∣
2
+
∣
E
∣
)
T=O(|V|^{2}+|E|)
T=O(∣V∣2+∣E∣)
⋆
\\star
⋆ 对于稠密图效果好
■ 方法2: 将dist存在最小堆中——
O
(
l
o
g
∣
V
∣
)
O( log|V|)
O(log∣V∣)
⋆
\\star
⋆ 更新dist[w]的值——
O
(
l
o
g
∣
V
∣
)
O( log|V|)
O(log∣V∣)
⋆
\\star
⋆
T
=
O
(
∣
V
∣
l
o
g
∣
V
∣
+
∣
E
∣
l
o
g
∣
V
∣
)
=
O
(
∣
E
∣
I
o
g
∣
V
∣
)
T= O(|V| log|V|+|E|log|V|)=O(|E| Iog|V|)
T=O(∣V∣log∣V∣+∣E∣log∣V∣)=O(∣E∣Iog∣V∣)
⋆
\\star
⋆ 对于稀疏图效果好
Dijkstra算法的步骤:
- step1:初始化所有dist为 ∞ \\infty ∞,初始化所有path为-1;
- step2:从顶点 v 1 v_{1} v1开始,寻找邻接点,更新 v 2 v_{2} v2和 v 4 v_{4} v4的dist和path;
- step3:找到与 v 1 v_{1} v1最近的邻接点(即dist最小) v 4 v_{4} v4,标记collected[ v 4 v_{4} v4]=true,并对 v 4 v_{4} v4继续寻找邻接点,更新 v 3 v_{3} v3、 v 5 v_{5} v5、 v 6 v_{6} v6和 v 7 v_{7} v7的dist和path;
- step4:继续在未收录定点中寻找dist最小的顶点 v 2 v_{2} v2,标记collected[ v 2 v_{2} v2]=true,并对 v 2 v_{2} v2继续寻找邻接点,对于 v 2 v_{2} v2的邻接点 v 5 v_{5} v5,若以 v 2 v_{2} v2为前一个顶点,dist[ v 5 v_{5} v5]=2+10=12>3,所以不更新 v 5 v_{5} v5的dist和path;
- step5:继续在未收录定点中寻找dist最小的顶点 v 3 v_{3} v3,标记collected[ v 3 v_{3} v3]=true,并对 v 3 v_{3} v3继续寻找邻接点,对于 v 3 v_{3} v3的邻接点 v 6 v_{6} v6,由于若以 v 3 v_{3} v3为前一个顶点,dist[ v 6 v_{6} v6]=3+5=8<9,所以更新 v 6 v_{6} v6的dist和path;
- step6:继续在未收录定点中寻找dist最小的顶点
v
5
v_{5}
v5,标记collected[
v
5
v_{5}
v5]=true,并对
v
5
v_{5}
v5继续寻找邻接点,对于
v
5
v_{5}
v5的邻接点
v
7
v_{7}
v7,若以
v
5
v_{5}
v以上是关于数据结构—— 图:最短路径问题的主要内容,如果未能解决你的问题,请参考以下文章
(王道408考研数据结构)第六章图-第四节3:最短路径之BFS算法(思想代码演示答题规范)
数据结构与算法图最短路径算法 ( Floyed 算法 | 图最短路径算法使用场景 | 求解图中任意两个点之间的最短路径 | 邻接矩阵存储图数据 | 弗洛伊德算法总结 )