最短路径采用迪杰斯特拉算法。
定义一位数组S[],记录源点到终点是否已经确定最短路径长度,0未确定,1确定。(也就是该点是否被查找过)
一维数组Path[],记录从源点到终点的当前最短路径上Vi的直接前驱顶点序号,从源点到Vi有弧,则Path[i]为V0,否则为-1。
一维数组D[],记录从源点到终点的当前最短路径长度,若源点到Vi有弧,则D[i]为弧上权值,否则为无穷大。
首先对源点到各点进行初始化,D[]中储存的都是和源点有弧的顶点与其的权值。S[]中除了源点下标对应的值为1以外,其余的都为0。Path[]中与源点有弧的点Vi,其Path[i]则为源点下标。(初始化结束)
然后,除去源点,就要对其他n-1个顶点进行查找。所以外部循环要进行n-1次,每一次初始化的min值为MaxInt,在剩下的点中找到一个未被查找过且与源点有路径,并且路径是最短的点Vi,然后将该点在S[i]中标记为1。然后判断源点到Vi的距离加上由Vi到其他未被查找的点Vj的距离是否小于源点到Vj的距离,如果小于,那么源点到Vj的路径及其长度更改为由源点到Vi,再由Vi到Vj,舍弃原始路径。并且将Vj的直接Path[]前驱改为Path[j]=i。
最后输出时,只需记录终点Vj对应Path[j]的值,一直索引到Path值为起点i即可。
路径查找的核心还是看D[],在路径的选择上,需要进行距离比较时,应该看此时D[]中储存的距离值,然后进行选择。
#define MaxInt 9999999
#define MaxNum 100
void ShortestPath_DIJ(AMGraph &G, int v0, int v1)
{
int S[MaxNum];
int Path[MaxNum];
int D[MaxNum];
int v;
int n = G.vexnum;
for (v = 0; v < n; v++)
{
S[v] = 0;
D[v] = G.arcs[v0][v];
if (D[v] < MaxInt)
{
Path[v] = v0;
}
else
{
Path[v] = -1;
}
}
S[v0] = 1;
D[v0] = 0;
//初始化结束
for (int i = 1; i < n; i++)//次数
{
int min = MaxInt;
for (int w = 0; w < n; w++)
{
if (!S[w] && D[w] < min)
{
v = w;
min = D[w];
}
}
S[v] = 1;
for (int w = 0; w < n; w++)
{
if (!S[w] && (D[v] + G.arcs[v][w] < D[w]))
{
D[w] = D[v] + G.arcs[v][w];
Path[w] = v;
}
}
}
cout << G.vexs[v0] << "到" << G.vexs[v1] << "的最短路径为:";
int pre = Path[v1];
cout << G.vexs[v1] << "-";
while (pre != v0)
{
cout << G.vexs[pre] << "-";
pre = Path[pre];
}
cout << G.vexs[v0];
cout << " 长度为:" << D[v1] << "米";
}