Dijkstra算法是一种单源最短路径算法,且算法要求图中不存在负权边,其伪代码如表
S
1
S1
S 1 所示。假设
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
v 1 ),在后续的解算过程中,每求解一条最短路径时,将其顶点加入到集合
S
S
S ,直至所有的顶点都在
S
S
S 中,结束算法;第二组是还未被解算的顶点集合
U
U
U ,将
U
U
U 中的顶点按照路径长度的递增顺序依次添加到顶点集合
S
S
S 中,且需要满足从源点
v
1
v_1
v 1 到集合
S
S
S 中每个顶点的最短距离要小于等于从源点
v
1
v_1
v 1 到集合
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,
{ v 1 ,
v
2
,
v_2,
v 2 ,
v
3
,
v_3,
v 3 ,
v
4
,
v_4,
v 4 ,
v
5
,
v_5,
v 5 ,
v
6
,
v_6,
v 6 ,
v
7
}
v_7\}
v 7 } ,
E
=
<
v
i
,
v
j
>
E = {<v_i, v_j>}
E = < v i , v j > , 所有的
i
,
j
=
[
1
,
7
]
i, j = [1, 7]
i , j = [ 1 , 7 ] ,求解以顶点
v
1
v_1
v 1 为源点的各个顶点的最短距离,算法示例步骤:
初始时,
S
S
S 中只有一个顶点(源点
v
1
v_1
v 1 ),
S
=
v
1
(
<
v
1
,
v
1
>
)
S = {v_1(<v_1, v_1>)}
S = v 1 ( < v 1 , v 1 > ) ,即
S
=
v
1
(
0
)
S = {v_1(0)}
S = v 1 ( 0 ) ;此时
U
U
U 中包含除
v
1
v_1
v 1 以外的所有点,若
v
1
v_1
v 1 与
U
U
U 中的顶点
u
u
u 有边,则
<
v
1
,
u
>
<v_1, u>
< v 1 , u > 有权值,反之,
<
v
1
,
u
>
<v_1, u>
< v 1 , u > 的权值为
∞
∞
∞ ,
U
=
v
i
(
<
v
1
,
v
i
>
)
U = {v_i(<v_1, v_i>)}
U = v i ( < v 1 , v i > ) , 所有的
i
=
[
2
,
7
]
i = [2, 7]
i = [ 2 , 7 ] ,即
U
U
U
=
=
=
{
v
2
(
12
)
,
\{v_2(12),
{ v 2 ( 1 2 ) ,
v
3
(
7
)
,
v_3(7),
v 3 ( 7 ) ,
v
4
(
∞
)
,
v_4(∞),
v 4 ( ∞ ) ,
v
5
(
23
)
,
v_5(23),
v 5 ( 2 3 ) ,
v
6
(
∞
)
,
v_6(∞),
v 6 ( ∞ ) ,
v
7
(
26
)
}
v_7(26)\}
v 7 ( 2 6 ) } 。
从
U
U
U 中取出最短的顶点
v
3
v_3
v 3 ,其权值为
7
7
7 ,将
v
3
v_3
v 3 加入
S
S
S 中,此时
S
=
{
v
1
(
0
)
,
S = \{v_1(0),
S = { v 1 ( 0 ) ,
v
3
(
7
)
}
v_3(7)\}
v 3 ( 7 ) } ;由于
<
v
3
,
v
4
>
<v_3, ~v_4>
< v 3 , v 4 > 的权值为
6
6
6 ,
<
v
1
,
v
4
>
<v_1, v_4>
< v 1 , v 4 >
=
=
=
<
v
1
,
v
3
>
<v_1, v_3>
< v 1 , v 3 >
+
+
+
<
v
3
,
v
4
>
<v_3, v_4>
< v 3 , v 4 >
=
13
= 13
= 1 3 ,小于
∞
∞
∞ ;即
U
U
U
=
=
=
{
v
2
(
12
)
,
\{v_2(12),
{ v 2 ( 1 2 ) ,
v
4
(
13
)
,
v_4(13),
v 4 ( 1 3 ) ,
v
5
(
23
)
,
v_5(23),
v 5 ( 2 3 ) ,
v
6
(
∞
)
,
v_6(∞),
v 6 ( ∞ ) ,
v
7
(
26
)
}
v_7(26)\}
v 7 ( 2 6 ) } 。
从
U
U
U 中取出最短的顶点
v
2
v_2
v 2 ,其权值为
12
12
1 2 ,将
v
2
v_2
v 2 加入
S
S
S 中,此时
S
=
{
v
1
(
0
)
,
v
3
(
7
)
,
v
2
(
12
)
}
S = \{v_1(0), v_3(7), v_2(12)\}
S = { v 1 ( 0 ) , v 3 ( 7 ) , v 2 ( 1 2 ) } ;由于
<
v
2
,
v
6
>
<v_2, v_6>
< v 2 , v 6 > 的权值为
11
11
1 1 ,
<
v
1
,
v
6
>
<v_1, v_6>
< v 1 , v 6 >
=
=
=
<
v
1
,
v
2
>
<v_1,v_2>
< v 1 , v 2 >
+
+
+
<
v
2
,
v
6
>
<v_2, v_6>
< v 2 , v 6 >
=
=
=
23
<
∞
23 < ∞
2 3 < ∞ ;由于
<
v
2
,
v
7
>
<v_2, v_7>
< v 2 , v 7 > 的权值为6,
<
v
1
,
v
7
>
<v_1, v_7>
< v 1 , v 7 >
=
=
=
<
v
1
,
v
2
>
<v_1, v_2>
< v 1 , v 2 >
+
+
+
<
v
2
,
v
7
>
<v_2, v_7>
< v 2 , v 7 >
=
18
<
26
= 18 < 26
= 1 8 < 2 6 ;即
U
=
U =
U =
{
v
4
(
13
)
,
\{v_4(13),
{ v 4 ( 1 3 ) ,
v
5
(
23
)
,
v_5(23),
v 5 ( 2 3 ) ,
v
6
(
23
)
,
v_6(23),
v 6 ( 2 3 ) ,
v
7
(
18
)
}
v_7(18)\}
v 7 ( 1 8 ) } 。
从
U
U
U 中取出最短的顶点
v
4
v_4
v 4 ,其权值为
13
13
1 3 ,将
v
4
v_4
v 4 加入
S
S
S 中,此时
S
S
S
=
{
v
1
(
0
)
,
= \{v_1(0),
= { v 1 ( 0 ) ,
v
3
(
7
)
,
v_3(7),
v 3 ( 7 ) ,
v
2
(
12
)
,
v_2(12),
v 2 ( 1 2 ) ,
v
4
(
13
)
}
v_4(13)\}
v 4 ( 1 3 ) } ;由于
<
v
4
,
v
5
>
<v_4, v_5>
< v 4 , v 5 > 的权值为
6
6
6 ,
<
v
1
,
v
5
>
<v_1, v_5>
< v 1 , v 5 >
=
<
v
1
,
v
4
>
= <v_1, v_4>
= < v 1 , v 4 >
+
<
v
4
,
v
5
>
+ <v_4, v_5>
+ < v 4 , v 5 >
=
19
<
23
= 19 < 23
= 1 9 < 2 3 ;即
U
=
U =
U =
{
v
5
(
19
)
,
\{v_5(19),
{ v 5 ( 1 9 ) ,
v
6
(
23
)
,
v_6(23),
v 6 ( 2 3 ) ,
v
7
(
18
)
}
v_7(18)\}
v 7 ( 1 8 ) } 。
从
U
U
U 中取出最短的顶点
v
7
v_7
v 7 ,其权值为
18
18
1 8 ,将
v
7
v_7
v 7 加入
S
S
S 中,此时
S
=
S =
S =
{
v
1
(
0
)
,
\{v_1(0),
{ v 1 ( 0 ) ,
v
3
(
7
)
,
v_3(7),
v 3 ( 7 ) ,
v
2
(
12
)
,
v_2(12),
v 2 ( 1 2 ) ,
v
4
(
13
)
,
v_4(13),
v 4 ( 1 3 ) ,
v
7
(
18
)
}
v_7(18)\}
v 7 ( 1 8 ) } ,
U
=
U =
U =
{
v
5
(
19
)
,
\{v_5(19),
{ v 5 ( 1 9 ) ,
v
6
(
23
)
}
v_6(23)\}
v 6 ( 2 3 ) } 。
从
U
U
U 中取出最短的顶点
v
5
v_5
v 5 ,其权值为
19
19
1 9 ,将
v
5
v_5
v 5 加入
S
S
S 中,此时
S
=
S =
S =
{
v
1
(
0
)
,
\{v_1(0),
{ v 1 ( 0 ) ,
v
3
(
7
)
,
v_3(7),
v 3 ( 7 ) ,
v
2
(
12
)
,
v_2(12),
v 2 ( 1 2 ) ,
v
4
(
13
)
,
v_4(13),
v 4 ( 1 3 ) ,
v
7
(
18
)
,
v_7(18),
v 7 ( 1 8 ) ,
v
5
(
19
)
}
v_5(19)\}
v 5 ( 1 9 ) } ;由于
<
v
5
,
v
6
>
<v_5, v_6>
< v 5 , v 6 > 的权值为
2
2
2 ,
<
v
1
,
v
6
>
<v_1, v_6>
< v 1 , v 6 >
=
<
v
1
,
v
5
>
= <v_1, v_5>
= < v 1 , v 5 >
+
<
v
5
,
v
6
>
+ <v_5, v_6>
+ < v 5 , v 6 >
=
21
<
23
= 21 < 23
= 2 1 < 2 3 ;即
U
=
{
v
6
(
21
)
}
U = \{v_6(21)\}
U = { v 6 ( 2 1 ) } 。
从
U
U
U 中取出最短的顶点
v
6
v_6
v 6 ,其权值为
21
21
2 1 ,将
v
6
v_6
v 6 加入
S
S
S 中,此时
S
S
S
=
{
v
1
(
0
)
,
= \{v_1(0),
= { v 1 ( 0 ) ,
v
3
(
7
)
,
v_3(7),
v 3 ( 7 ) ,
v
2
(
12
)
,
v_2(12),
v 2 ( 1 2 ) ,
v
4
(
13
)
,
v_4(13),
v 4 ( 1 3 ) ,
v
7
(
18
)
,
v_7(18),
v 7 ( 1 8 ) ,
v
5
(
19
)
,
v_5(19),
v 5 ( 1 9 ) ,
v
6
(
21
)
}
v_6(21)\}
v 6 ( 2 1 ) } ,
U
=
∅
U = ∅
U = ∅ 。
此时
U
=
∅
U = ∅
U = ∅ ,已经获取到以
v
1
v_1
v 1 为源点的各个顶点的最短距离,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 ;
}