模板
/*
* Dijkstra最短路径: 求出 源点 到其它所有顶点最短的距离,以及相应的路径
* 参数说明:
* G -- 图
* vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
* prev -- 前驱顶点数组。即,prev[i]的值是"源点vs"到"顶点i"的最短路径中,位于"顶点i"之前的那个顶点值,从后往前可以打印出完整路径。
* dist -- 即distance,距离数组。dist[i]记录的是"源点vs"到"顶点i"的最短路径的长度。
*/
void dijkstra(Graph G, int vs, int prev[], int dist[])
{
int i,j,k;
int min;
int tmp;
int flag[MAX]; // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。
// 初始化 distance数组,也就是 dist数组,把题目中已有的边输入进去
for (i = 0; i < G.vexnum; i++)
{
flag[i] = 0; // 顶点i的最短路径还没获取到。
prev[i] = 0; // 顶点i的前驱顶点为0。
dist[i] = G.matrix[vs][i];// 顶点i的最短路径为"顶点vs"到"顶点i"的权。
}
// 对"顶点vs"自身进行初始化
//已选中区域S开始时只有源点vs自己
flag[vs] = 1;
dist[vs] = 0;
// 遍历所有顶点;每次找出到达一个顶点的最短路径。
for (i = 1; i < G.vexnum; i++)
{
// 寻找当前距离 已选中区域 最近的点j, 并把这个点标记为已访问,即flag[j] = 1;
// 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
min = INF;
for (j = 0; j < G.vexnum; j++)
{
if (flag[j]==0 && dist[j]<min)
{
min = dist[j];
k = j;
}
}
// 标记"顶点k"为当前距离 已选中区域 最近的点,加入 已选中区域S, 即 flag[k] = 1, 就代表已经被加入S集合;
flag[k] = 1;
//用 这一轮 选中的顶点k, 来更新目前所有的点到源点vs的距离,因为 dist[k]是源点vs到 k点的距离, 然后再加上k到j的距离:matrix[k][j],就是源点vs到j的距离,求出这些距离了之后留着备用,用在下一轮循环里面找出 还未被加入已选中区域并且已选中区域最近的点
for (j = 0; j < G.vexnum; j++)
{
tmp = (G.matrix[k][j]==INF ? INF : (dist[k] + G.matrix[k][j])); // 防止溢出
//注意:只有flag[j]=0,即之前未被加入已选中区域才会对其更新,因为对于已经加入已选中区域的点,当初把它们加入S的时候就证明它们是当时离源点vs最近的点
if (flag[j] == 0 && (tmp < dist[j]) )
{
dist[j] = tmp;
//更新前驱节点,这样知道 最短路径上每个节点之前是从哪个节点过来的,从后往前可以打印出完整路径
prev[j] = k;
}
}
}
// 打印dijkstra最短路径的结果
printf("dijkstra(%c): \n", G.vexs[vs]);
for (i = 0; i < G.vexnum; i++)
printf(" shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);
}