当前位置:文档之家› D算法

D算法

最短路径
--------------------------------------------------------------------------------
从某源点到其余顶点之间的最短路径
设有向网G=(V,E),以某指定顶点为源点v0,求从v0出发到图中所有其余各项点的最短路径。

以图5-5-1所示的有向网络为例,
若指定v0为源点,通过分析可以得到从v0出发到其余各项点的最短路径和路径长度为:
v0 → v1 :无路径
v0 → v2 :10
v0 → v3 :50 (经v4)
v0 → v4 :30
v0 → v5 :60 (经v4、v3)
图5-5-1 带权有向图
如何在计算机中求得从v0到其余各项点的最短路径呢?迪杰斯特拉(Dijkstra)于1959年提出了一个按路径长度递增的次序产生最短路径的算法。

其基本思想是:把图中所有顶点分成两组,第一组包括已确定最短路径的顶点(初始只包括顶点v0),第二组包括尚未确定最短路径的顶点,然后按最短路径长度递增的次序逐个把第二组的顶点加到第一组中去,直至从v0出发可以到达的所有顶点都包括到第一组中。

在这过程中,总保持从v0到第一组各顶点的最短路程长度都不大于从v0到第二组的任何顶点的最短路径长度。

另外,每一个顶点对应一个距离值,第一组的顶点对应的距离值就是从v0到此顶点的只包括第一组的顶点为中间顶点的最短路径长度。

设有向图G有n个顶点(v0为源点),其存储结构用邻接矩阵表示。

算法实现时需要设置三个数组s[n]、dist[n]和path[n]。

s用以标记那些已经找到最短路径的顶点,若s[i]=1,则表示已经找到源点到顶点vi的最短路径,若s[i]=0,则表示从源点到顶点vi的最短路径尚未求得,数组的初态只包括顶点v0,即s[0]=1。

数组dist记录源点到其他各顶点当前的最短距离,其初值为:
dist[i]=G.arcs[0][i] i=1,2,…,n-1
path是最短路径的路径数组,其中path[i]表示从源点v0到顶点vi之间的最短路径上该顶
点的前驱顶点,若从源点到顶点vi无路径,
则path[i]=-1。

算法执行时从s以外的顶点集合V-S中选出一个顶点vw,使dist[w]的值最小。

然后将vw加入集合s中,即s[w]=1;同时调整集合V-S中的各个顶点的距离值:从原来的dist[j]和dist[w]+cost[w][j]中选择较小的值作为新的dist[j]。

以图5-5-1为例,当集合s中只有v0时,dist[3]= ∞,当加入顶点v4后,使dist[4]+cost[4][3]<dist[3],因此将dist[3]更新为50。

重复上述过程,直到s中包含图中所有顶点,或再也没有可加入到s中的顶点为止。

采用迪杰斯特拉算法求最短路径的算法描述如下:
算法5.8
void Dijkstra(Mgraph Gn, int v0,int path[],int dist[]){
/* 求有向网Gn的v0顶点到其余顶点v的最短路径,path[v]是v0到v的最短路径
上的前驱顶点,dist[v]是路径长度*/
int s[VEX_NUM];
for(v=0; v<VEX_NUM; v++){ /*初始化s、dist和path*/
s[v]=0; dist[v]=Gn.arcs[v0][v];
if(dist[v]<MAXINT) path[v]=v0;
else path[v]=-1;
}
dist[vo]=0;s[v0]=1; /*初始时源点v0∈S集*/
/* 循环求v0到某个顶点v的最短路径,并将v加入S集*/
for(i=1;i<VEX_NUM -1;i++){
min=MAXINT;
for(w=0;w<VEX_NUM;w++)
if(!s[w] && dist[w]<min)
{ /*顶点w不属于S集且离v0更近*/
v=w;min=dist[w];
}
s[v]=1; /*顶点v并入S*/
for(j=0;j<VEX_NUM;j++) /*更新当前最短路径及距离*/
if(!s[j] && (min+Gn.arcs[v][j]<dist[j]))
{
dist[j]=min+Gn.arcs[k][j];
path[j]=v;
}/*if*/
}/*for*/
}/*Dijkstra*/
void Putpath(int v0,int p[],int d[]){
/*输出源点v0到其余顶点的最短路径和路径长度*/
for(i=0;i<VEX_UNM;i++)
if(d[i]<MAXINT && i!=v0){
printf("v%d<--",i);
next=p[i];
while(next!=v0){
printf("v%d<--",next);
next=p[next];
}
printf("v%d:%d\n",v0,d[i]);
else
if(i!=v0) printf("v%d<--v%d:no path\n",i,v0); }/*Putpath*/
(满屏显示)。

相关主题