在一个无权的图中
,
若从一顶点到另一顶点存在着一条路径
,
则称该路径长度为该路径上所经过的边的数目
,
它等于该路径上的顶点数减
1
。由于从一顶点到另一顶点可能存在着多条路径
,
每条路径上所经过的边数可能不同
,
即路径长度不同
,
我们把路径长度最短
(
即经过的边数最少
)
的那条路径叫做
最短路径
,
其路径长度叫做最短路径长度或最短距离。
S U v0 到0~6各顶点的距离
Dijkstra
算法的具体C语言实现:
对于带权的图
,
考虑路径上各边上的权值,则通常把一条路径上所经边的权值之和定义为该路径的
路径长度
或称
带权路径长度
。从源点到终点可能不止一条路径,把带权路径长度最短的那条路径称为最短路径
,
其路径长度
(
权值之和
)
称为最短路径长度或者最短距离。
如何求从一个顶点到其余各点的最短路径?
Dijkstra
提出了一种按路径长度递增的次序产生最短路径的算法。如下图:
l
Dijkstra
算法思想
基本思想是:设G=(V,E)是一个带权有向图, 把图中顶点集合V分成两组:
第一组为
已求出最短路径的顶点集合S
(初始时S中只有一个源点,以后每求得一条最短路径v
0
,
…
v
k
,就将v
k
加入到集合S中,直到全部顶点都加入到S中,算法就结束了)
第二组为其余
未确定最短路径的顶点集合U
。
按最短路径长度的递增次序依次
把U中的顶点加入S
中。在加入的过程中,总保持从源点v
0
到S中各顶点的最短路径长度不大于从源点v
0
到U中任何顶点的最短路径长度。
为
每个顶点定义一个辅助参量:
距离
,S中顶点距离就是从v
0
到此顶点的最短路径长度,U中顶点距离从v
0
到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
Dijkstra
算法的具体步骤:
设
S
为已经求得的最短路径的顶点集合,
dist[i]
表示
v
0
到
v
i
的最短路径。
(1)S={v
0
}
,
dist[i]=cost [v
0
][v
i
] //初始化
(2)
选择
u
,使得
dist[u]=min{dist[i] |
v
i
不在
S
中
},
则
u
为当前求得的一条从
v
0
出发的最短路径的终点,让
S=S+{u},即S集合中加入顶点u。
(3)
修改所有不在
S
中的顶点
Vi
的最短路径长度 //这是因为集合S中新增了顶点,则需要更新U中顶点距离从v0到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
if dist[u]+cost[u][v
i
]<dist[i]
dist[v
i
]= dist[u]+cost[u][v
i
]
(4)
重复步骤
(2)
和
(3)
直到所有顶点都包含在
S
中。
如图:
{0} {1,2,3,4,5,6} {0,4,6,6,∞,∞,∞}
{0,1} {2,3,4,5,6} {0,4,5,6,11,∞,∞}
{0,1,2} {3,4,5,6} {0,4,5,6,11,9,∞}
{0,1,2,3} {4,5,6} {0,4,5,6,11,9,∞}
{0,1,2,3,5} {4,6} {0,4,5,6,10,9,17}
{0,1,2,3,5,4} {6} {0,4,5,6,10,9,16}
{0,1,2,3,5,4,6} {} {0,4,5,6,10,9,16}
则v0到v1~v6各顶点的最短距离分别为4、5、6、10、9和16。
void dijkstra(int cost[][MAXNODE],int n,int v0,int Distance[])
{
int s[MAXNODE];
int mindis,dis;
int i,j,u;
/*初始化*/
for(i=0;i<n;i++)
{
Distance[i]=cost[v0][i];
s[i]=0;
}
s[v0]=1 /*标记v0*/
/*在当前还未找到最短路径的顶点集中选取具有最短距离的顶点u*/
for(i=1;i<n;i++)
{
mindis=MaxCOST;
for(j=1;j<n;j++)
if (s[j]==0 && DIstance[j]<mindis)
{
u=j;
mindis=Distance[j];
}
s[u]=1; /*标记u*/
/*修改从v0到其他顶点的最短距离*/
for(j=1;j<n;j++)
if (s[j]==0)
{
dis=Distance[u]+cost[u][j];
Distance[j]=(Distance[j]<dis)?Distance[j]:dis;
}
}
}
时间复杂度有点高,o(n^2)
{
int s[MAXNODE];
int mindis,dis;
int i,j,u;
/*初始化*/
for(i=0;i<n;i++)
{
Distance[i]=cost[v0][i];
s[i]=0;
}
s[v0]=1 /*标记v0*/
/*在当前还未找到最短路径的顶点集中选取具有最短距离的顶点u*/
for(i=1;i<n;i++)
{
mindis=MaxCOST;
for(j=1;j<n;j++)
if (s[j]==0 && DIstance[j]<mindis)
{
u=j;
mindis=Distance[j];
}
s[u]=1; /*标记u*/
/*修改从v0到其他顶点的最短距离*/
for(j=1;j<n;j++)
if (s[j]==0)
{
dis=Distance[u]+cost[u][j];
Distance[j]=(Distance[j]<dis)?Distance[j]:dis;
}
}
}