Dijkstra算法是一种单源最短路径算法,且算法要求图中不存在负权边,其伪代码如表 S 1 S1 S1 所示。假设 G = ( V , E ) G = (V, E) G=(V,E) 是一个带权的有向图,在图 G G G 中把顶点集合 V V V 分为两组:第一组是已经求出最短路径的顶点集合 S S S,初始的 S S S 只有一个顶点(源点 v 1 v_1 v1),在后续的解算过程中,每求解一条最短路径时,将其顶点加入到集合 S S S,直至所有的顶点都在 S S S 中,结束算法;第二组是还未被解算的顶点集合 U U U,将 U U U 中的顶点按照路径长度的递增顺序依次添加到顶点集合 S S S 中,且需要满足从源点 v 1 v_1 v1 到集合 S S S 中每个顶点的最短距离要小于等于从源点 v 1 v_1 v1 到集合 U U U 中任何一个顶点的最短距离。
表S1 Dijkstra算法伪代码
for each node v
dis(v) ← +∞
previous (v) ← undefined
dis(source) ← 0
while num(S) < n ▷ S为顶点集合
u ← node with smallest distance
Remove u
for each node v in S
alt ← dis(u) + dis(u,v)
if alt < dis(v) then
dis(v) ← alt ▷ 更新距离
previous(v) ← u
如上图所示,
G
=
(
V
,
E
)
G = (V, E)
G=(V,E) 是一个带权的有向图,其中
V
V
V
=
=
=
{
v
1
,
\{v_1,
{v1,
v
2
,
v_2,
v2,
v
3
,
v_3,
v3,
v
4
,
v_4,
v4,
v
5
,
v_5,
v5,
v
6
,
v_6,
v6,
v
7
}
v_7\}
v7},
E
=
<
v
i
,
v
j
>
E = {<v_i, v_j>}
E=<vi,vj>, 所有的
i
,
j
=
[
1
,
7
]
i, j = [1, 7]
i,j=[1,7],求解以顶点
v
1
v_1
v1 为源点的各个顶点的最短距离,算法示例步骤:
- 初始时, S S S 中只有一个顶点(源点 v 1 v_1 v1), S = v 1 ( < v 1 , v 1 > ) S = {v_1(<v_1, v_1>)} S=v1(<v1,v1>),即 S = v 1 ( 0 ) S = {v_1(0)} S=v1(0);此时 U U U 中包含除 v 1 v_1 v1 以外的所有点,若 v 1 v_1 v1 与 U U U 中的顶点 u u u 有边,则 < v 1 , u > <v_1, u> <v1,u> 有权值,反之, < v 1 , u > <v_1, u> <v1,u> 的权值为 ∞ ∞ ∞, U = v i ( < v 1 , v i > ) U = {v_i(<v_1, v_i>)} U=vi(<v1,vi>), 所有的 i = [ 2 , 7 ] i = [2, 7] i=[2,7],即 U U U = = = { v 2 ( 12 ) , \{v_2(12), {v2(12), v 3 ( 7 ) , v_3(7), v3(7), v 4 ( ∞ ) , v_4(∞), v4(∞), v 5 ( 23 ) , v_5(23), v5(23), v 6 ( ∞ ) , v_6(∞), v6(∞), v 7 ( 26 ) } v_7(26)\} v7(26)}。
- 从 U U U 中取出最短的顶点 v 3 v_3 v3,其权值为 7 7 7,将 v 3 v_3 v3 加入 S S S 中,此时 S = { v 1 ( 0 ) , S = \{v_1(0), S={v1(0), v 3 ( 7 ) } v_3(7)\} v3(7)};由于 < v 3 , v 4 > <v_3, ~v_4> <v3, v4> 的权值为 6 6 6, < v 1 , v 4 > <v_1, v_4> <v1,v4> = = = < v 1 , v 3 > <v_1, v_3> <v1,v3> + + + < v 3 , v 4 > <v_3, v_4> <v3,v4> = 13 = 13 =13,小于 ∞ ∞ ∞;即 U U U = = = { v 2 ( 12 ) , \{v_2(12), {v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 5 ( 23 ) , v_5(23), v5(23), v 6 ( ∞ ) , v_6(∞), v6(∞), v 7 ( 26 ) } v_7(26)\} v7(26)}。
- 从 U U U 中取出最短的顶点 v 2 v_2 v2,其权值为 12 12 12,将 v 2 v_2 v2 加入 S S S 中,此时 S = { v 1 ( 0 ) , v 3 ( 7 ) , v 2 ( 12 ) } S = \{v_1(0), v_3(7), v_2(12)\} S={v1(0),v3(7),v2(12)};由于 < v 2 , v 6 > <v_2, v_6> <v2,v6> 的权值为 11 11 11, < v 1 , v 6 > <v_1, v_6> <v1,v6> = = = < v 1 , v 2 > <v_1,v_2> <v1,v2> + + + < v 2 , v 6 > <v_2, v_6> <v2,v6> = = = 23 < ∞ 23 < ∞ 23<∞;由于 < v 2 , v 7 > <v_2, v_7> <v2,v7> 的权值为6, < v 1 , v 7 > <v_1, v_7> <v1,v7> = = = < v 1 , v 2 > <v_1, v_2> <v1,v2> + + + < v 2 , v 7 > <v_2, v_7> <v2,v7> = 18 < 26 = 18 < 26 =18<26;即 U = U = U= { v 4 ( 13 ) , \{v_4(13), {v4(13), v 5 ( 23 ) , v_5(23), v5(23), v 6 ( 23 ) , v_6(23), v6(23), v 7 ( 18 ) } v_7(18)\} v7(18)}。
- 从 U U U 中取出最短的顶点 v 4 v_4 v4,其权值为 13 13 13,将 v 4 v_4 v4 加入 S S S 中,此时 S S S = { v 1 ( 0 ) , = \{v_1(0), ={v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) } v_4(13)\} v4(13)};由于 < v 4 , v 5 > <v_4, v_5> <v4,v5> 的权值为 6 6 6, < v 1 , v 5 > <v_1, v_5> <v1,v5> = < v 1 , v 4 > = <v_1, v_4> =<v1,v4> + < v 4 , v 5 > + <v_4, v_5> +<v4,v5> = 19 < 23 = 19 < 23 =19<23;即 U = U = U= { v 5 ( 19 ) , \{v_5(19), {v5(19), v 6 ( 23 ) , v_6(23), v6(23), v 7 ( 18 ) } v_7(18)\} v7(18)}。
- 从 U U U 中取出最短的顶点 v 7 v_7 v7,其权值为 18 18 18,将 v 7 v_7 v7 加入 S S S 中,此时 S = S = S= { v 1 ( 0 ) , \{v_1(0), {v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 7 ( 18 ) } v_7(18)\} v7(18)}, U = U = U= { v 5 ( 19 ) , \{v_5(19), {v5(19), v 6 ( 23 ) } v_6(23)\} v6(23)}。
- 从 U U U 中取出最短的顶点 v 5 v_5 v5,其权值为 19 19 19,将 v 5 v_5 v5 加入 S S S 中,此时 S = S = S= { v 1 ( 0 ) , \{v_1(0), {v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 7 ( 18 ) , v_7(18), v7(18), v 5 ( 19 ) } v_5(19)\} v5(19)};由于 < v 5 , v 6 > <v_5, v_6> <v5,v6> 的权值为 2 2 2, < v 1 , v 6 > <v_1, v_6> <v1,v6> = < v 1 , v 5 > = <v_1, v_5> =<v1,v5> + < v 5 , v 6 > + <v_5, v_6> +<v5,v6> = 21 < 23 = 21 < 23 =21<23;即 U = { v 6 ( 21 ) } U = \{v_6(21)\} U={v6(21)}。
- 从 U U U 中取出最短的顶点 v 6 v_6 v6,其权值为 21 21 21,将 v 6 v_6 v6 加入 S S S 中,此时 S S S = { v 1 ( 0 ) , = \{v_1(0), ={v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 7 ( 18 ) , v_7(18), v7(18), v 5 ( 19 ) , v_5(19), v5(19), v 6 ( 21 ) } v_6(21)\} v6(21)}, U = ∅ U = ∅ U=∅。
- 此时 U = ∅ U = ∅ U=∅,已经获取到以 v 1 v_1 v1 为源点的各个顶点的最短距离,Dijkstra算法结束。
附C++代码:
#define DB_MAX 100000000.0
bool dijkstra(float** pathvalue, int pointnum, int v, float* dist, int* path)
{
int n = pointnum;
bool *S = new bool[n];
int i, j, k;
float w, min;
for (i = 0; i < n; ++i)
{
dist[i] = pathvalue[v][i];
S[i] = false;
if(i != v && dist[i] < DB_MAX)
path[i] = v;
else
path[i] = -1;
}
S[v] = true;
dist[v] = 0;
for (i = 0; i < n-1; ++i)
{
min = DB_MAX;
int u = v;
for (j = 0; j < n; ++j)
{
if(S[j] == false && dist[j] < min)
{
u = j;
min = dist[j];
}
}
S[u] = true;
for (k = 0; k < n; ++k)
{
w = pathvalue[u][k];
if(S[k] == false && w < DB_MAX && dist[u] + w < dist[k])
{
dist[k] = dist[u] + w;
path[k] = u;
}
}
}
return true;
}