1. 问题描述
单源点最短路径:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。
2. 迪杰斯特拉(Dijkstra)算法
迪杰斯特拉算法按照最短路径递增的次序产生最短路径。具体参见数据结构。
3. 算法实现
采用邻接矩阵作为其存储结构。
void dijkstra(MGraph *G, int v0, int (*P)[G->vexnum], int D[])
{
/**若P[v][w]=1, 则w是从v0到v当前求得最短路径上的顶点*/
int i, v, w, min, final[G->vexnum];
v0 = v0 - 1;
memset(final, 0, sizeof(final)); //false:0 true:1
for (v = 0;v < G->vexnum;v++) {
D[v] = G->arcs[v0][v]; //D[i]表示当前所找到的从始点v到每个终点vi的最短路径的长度
memset(P[v], 0, sizeof(int) * G->vexnum); //set empty path
if (D[v] < INT_MAX) {
P[v][v0] = 1;
P[v][v] = 1;
/** debugging */
//printf("P[%d][%d] = 1, p[%d][%d] = 1\n", v, v0,v,v);
}
} //for
D[v0] = 0;
final[v0] = 1;
for (i = 1;i < G->vexnum;i++) {
min = INT_MAX;
for (w = 0;w < G->vexnum;w++) // find the current min
if (final[w] == 0)
if (D[w] < min) {
v = w;
min = D[w];
}
final[v] = 1; //the current minist path: V0...Vv
for (w = 0;w < G->vexnum;w++) { // update the current path and its cost
/** debugging */
//printf("D[%d]=%d, G.arcs[%d][%d]=%d\n", w, D[w],v, w, G->arcs[v][w]);
if (final[w] ==0 && (G->arcs[v][w] < INT_MAX) && (min + G->arcs[v][w]) < D[w]) {
/* when G->arcs[v][w] is equal to INT_MAX, (min + G->arcs[v][w]) overflows,
* its value less than zero
*/
D[w] = min + G->arcs[v][w];
//P[w] = P[v];
memcpy(P[w], P[v], sizeof(P[v]));
/*
for (j = 0;j < G->vexnum;j++)
P[w][j] = P[v][j];
*/
*(P[w] + w) = 1;
}// if
}
} //for
/** debugging */
for (i = 0;i < G->vexnum;i++)
printf("min{V%d->V%d} = %d\n", v0, i + 1, D[i]);
printf("\n");
printf("path:\n");
for (v = 0;v < G->vexnum;v++){
for (w = 0;w < G->vexnum;w++)
printf("P[%d][%d]=%d,", v, w, P[v][w]);
printf("\n");
}
}
/**
6
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
5 4 20
5 6 60
0 0 0
*/
4. 测试输出
5. 时间复杂度
设n为顶点树、数,算法时间复杂度为O(n^2)。