在非网图中,最短路径是指两顶点之间经历的边数最少的路径。
在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径。
Dijkstra算法
基本思想:
1、设置一个集合S存放已经找到最短路径的顶点,S的初始状态只包含源点v,
2、对vi∈V-S,假设从源点v到vi的有向边为最短路径(从v到其余顶点的最短路径的初
值)。
3、以后每求得一条最短路径v, …, vk,就将vk加入集合S中,并将路径v, …, vk , vi与
原来的假设相比较,取路径长度较小者为最短路径。
4、重复上述过程,直到集合V中全部顶点加入到集合S中。
路径长度最短的最短路径(即第一条最短路)的特点:
在这条路径上,必定只含一条边,并且这条边上的权值最小。
下一条路径长度次短的最短路径的特点:
它只可能有两种情况:
或者是直接从源点到该点(只含一条边);
或者是从源点经过顶点v1(第一条最短路径所依附的顶点),再到达该顶点(由两条
边组成)。
再下一条路径长度次短的最短路径的特点:
它可能有四种情况:或者是直接从源点到该点(只含一条边); 或者从源点经过顶点
v1,再到达该顶点(由两条边组成);或者是从源点经过顶点v2,再到达该顶点(两
条条边);或者是从源点经过顶点v1、v2,再到达该顶点(多条边)。
其余最短路径的特点:
它或者是直接从源点到该点(只含一条边); 或者是从源点经过已求得最短路径的
顶点(集合S中的顶点),再到达该顶点。
数据结构 :
图的存储结构:邻接矩阵存储结构
数组dist[n]:每个分量dist[i]表示当前所找到的从始点v到终点vi的最短路径的长
度。初态为:
若从v到vi有弧,则dist[i]为弧上权值;否则置dist[i]为∞。
数组path[n]:path[i]是一个字符串,表示当前所找到的从始点v到终点vi的最短路
径。初态为:若从v到vi有弧,则path[i]为vvi;否则置path[i]空串。
数组s[n]:存放源点和已经找到最短路径的终点,其初态为只有一个源点v。
const int MAX=1000;
void Dijkstra(MGraph g, int v){
for ( i =0; i<g.vexnum ; i++){
dist[i]=g.arcs[v][i];
if ( dist[i]!= MAX)
path [i]=g.vertex[v]+g.vertex[i];
else
path[i]=“”;
}
S[0]=g.vertex[v];
num=1;
While (num<g.vextexNum){
k=0;
for(i=0;i<G.vertexNum;i++)
if((dist[i]<dist[k]) k=i
cout<<dist[k]<<path[k];
s[num++]=G.vertex[k];
for(i=0;i<G.vertexNum;i++)
if(dist[k]+g.arc[k][i]<dist[i] {
dist[i]=dist[k]+g.arc[k][i];
path[i]=path[k]+g.vertex[i];
}
}
}
Floyd算法
基本思想如下:
设图g用邻接矩阵法表示,
求图g中任意一对顶点vi、 vj间的最短路径。
将vi到vj 的最短的路径长度初始化为(vi,vj), 然后进行如下n次比较
和修正:
在vi、vj间加入顶点v0,比较(vi, v0, vj)和(vi, vj)的路径的长度,
取其中较短的路径作为vi到vj的且中间顶点号不大于0的最短路径。
在vi、vj间加入顶点v1,
得(vi, …,v1)和(v1, …,vj),其中:
(vi, …, v1)是vi到v1 的且中间顶点号不大于0的最短路径,
(v1, …, vj) 是v1到vj 的且中间顶点号不大于0的最短路径,
这两条路径在上一步中已求出。
将(vi, …, v1, …, vj)与上一步已求出的且vi到vj 中间顶点号不大于0的最
短路径比较,取其中较短的路径作为vi到vj 的且中间顶点号不大于1的最短路
径。
在vi、vj间加入顶点v2,得
(vi, …, v2)和(v2, …, vj), 其中:
(vi, …, v2)是vi到v2 的且中间顶点号不大于1的最短路径,
(v2, …, vj) 是v2到vj 的且中间顶点号不大于1的最短路径,
这两条路径在上一步中已求出。
将(vi, …, v2, …, vj)与上一步已求出的且vi到vj 中间顶点号不大于
1的最短路径比较, 取其中较短的路径作为vi到vj 的且中间顶点号不大
于2的最短路径。
图的存储结构:带权的邻接矩阵存储结构
数组dist[n][n]:存放在迭代过程中求得的最短路径长度。迭代公式:
dist-1[i][j]=edge[i][j]
dist k[i][j]=min{disk-1[i][j],disk-1[i][k]+disk-1[k][j]}
0≤k≤n-1
数组path[n][n]:
存放从vi到vj的最短路径,初始为path[i][j]="vivj"。
void Floyd(MGraph G)
{
for (i=0; i<G.vertexNum; i++)
for (j=0; j<G.vertexNum; j++)
{
dist[i][j]=G.arc[i][j];
if (dist[i][j]!=∞)
path[i][j]=G.vertex[i]+G.vertex[j];
else path[i][j]="";
}
for (k=0; k<G.vertexNum; k++)
for (i=0; i<G.vertexNum; i++)
for (j=0; j<G.vertexNum; j++)
if (dist[i][k]+dist[k][j]<dist[i][j]) {
dist[i][j]=dist[i][k]+dist[k][j];
path[i][j]=path[i][k]+path[k][j];
}
}