关于求最短路径的问题准备分两次来写,每次分别描述一种算法。这一次我们讲述迪杰斯特拉(Dijkstra)算法。
这是一个按路径长度递增的次序产生最短路径的算法。 结合上图我们来讲一讲这个算法的大体思路,假设我们要求从V0到V8的最短路径。我们先求出从V0到V1的距离,然后根据V1相连的边,还可以求出V0-V1-V2=1+3=4和V0-V1-V4=1+7=8以及V0-V1-V3=1+5=6。现在说V0到V2的距离很明显应该是V0-V1-V2=4比直接从V0-V2=5要更小。从这点就可以看出,这个迪杰斯特拉(Dijkstra)并不是直接求出V0到V8的距离,而是一步步求V0到每一个顶点的距离,而是在已经求出的最短路径的基础上求得更远顶点的距离,相当于几乎求了所有顶点到V0的距离。
下面我们来看代码:#define MAXVEX 9 //顶点数量
#define INFINITY 65525 // C语言表示无穷大
typedef int Pathmatirx[MAXVEX]; // 用于存储V0到各顶点最短路径下标的数组
typedef int ShortPathTable[MAXVEX];
/Dijkstra 算法,求有向网G的顶点到其余顶点B的最短路径P[v]及带权长度D[v]/
void ShortestPath_Dijkstra(MGra G, int v0, Pathmatirx p, ShortPathTable D)
{
int v, w, k, min;
int final[MAXVEX];/=1 表示V0到Vn的最短路径已经求出/
for (v = 0; v < G.numVertexesl; v++) //初始化模块
{
final[v] = 0;
(*D)[v] = G.matirx[v0][v];//获取与v0有边的顶点边权值
(*p)[v] = 0;
}
(*D)[v0] = 0; // v0-v0距离为0
final[v0] = 1;//v0-v0不用求
//开始主循环,每次求得v0到某个顶点v顶点的最短路径
for (v = 1; v < G.numVertexes; v++)
{
min = INFINITY;
for (w = 1; w < G.numVertexes; w++)
{
if (!final[w] && (*D)[w] < min)
{
k = w;
min = (*D)[w]; /*w顶点v0顶点更近*/
}
}
final[k] = 1;//将当前找到的最近的顶点置为1
for (w = 1; w < G.numVertexes; w++)// 修正当前最短路径和距离, 同时还求了当前最短路径的顶点到相邻顶点的距离
{
/*如果经过v顶点的路径比现在这路径的长度短的话*/
if (!final[w] && (min + G.matirx[k][w] < (*D)[w])
{
/*说明找到了更短的路径*/
(*D)[w] = min + G.matirx[k][w];
(*p)[w] = k;
}
}
}
}