算法的基本思路:
每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径
基本步骤:
1.将所有的顶点分为两部分:已知最短路程的顶点集合P和未知最 短路径的顶点集合Q。最开始,已知最短路径的顶点集合P中只有源点一个顶点。我们这里用一个book数组来记录哪些点在集合P中。
例如对于某个顶点i,如果book[i]=1 -->顶点在集合P内
book[i]=0 -->顶点在集合Q内
2.设置源点s到自己的最短路径为0即dis[s]=0。若存在有源点能直接到达的顶点i,则吧dis[i]设为e[s][i]。同时把所有其他(源点不能直接到达的)顶点的最短路径设为INF
3.在集合Q点所有顶点中选择一个离源点s最近的顶点u(即dis[u]最小) 加入到集合P。并考察所有以点u为起点的边,对每一条边进行松弛操作 例如存在一条从u到v的边,那么可以通过将边u->v添加到尾部来拓展一条从s到v的路径,这条路径的长度是dis[u]+e[u][v]。若这个值比目前 已知的dis[v]的值要小,我们可以用新值来替代当前dis[v]中的值
4.重复第3步,若集合Q为空,算法结束。最终dis数组中的值就是源点到所有顶点的最短路径
完整代码如下:
#include<stdio.h>
int main(){
int e[10][10],dis[10],book[10];
//e数组为邻接矩阵
//dis数组存储的为从源点到各点的最小路程
//book数组
int i,j,u,v; //计数作用
int n,m,t1,t2,t3,min;
//n,m分别代表顶点个数和边的条数
//t1,t2,t3 --> 顶点t1到顶点t2的路程为t3
//min 找最短的路径
int INF = 999999999; //无穷大值
scanf("%d%d",&n,&m); //输入顶点个数与边的条数
//初始化邻接矩阵,将所有值设为无穷大
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
e[i][j] = 0;
else
e[i][j] = INF;
//输入t1,t2,t3
for(i=1;i<=m;i++){
scanf("%d%d%d",&t1,&t2,&t3);
e[t1][t2] = t3;
}
//初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
for(i=1;i<=n;i++)
dis[i] = e[1][i];
//book数组初始化
for(i=1;i<=n;i++)
book[i] = 0;
book[1] = 1;//1为顶点,本身就在P数组中
//Dijkstra算法核心语句
for(i=1;i<n-1;i++){
//找到离1号顶点最近的顶点
min = INF;
for(j=1;j<=n;j++){
if(book[j]==0 && dis[j]<min){
min = dis[j];
u = j;
}
}
book[u]=1;
for(v=1;v<=n;v++){
if(e[u][v]<INF){
//若有路,则判断下直接到达与绕路的路程权重哪个更小
if(dis[v]>dis[u]+e[u][v])
dis[v] = dis[u]+e[u][v];
}
}
}
/*
* input 6 9 output 0 1 8 4 13 17
* 1 2 3
* 1 3 12
* 2 3 9 e[7][7]:
* 2 4 3 0|
* 3 5 5 0---1---2---3---4---5---6---->到达点
* 4 3 4 1|0 3 12 INF INF INF
* 4 5 13 2|INF 0 9 3 INF INF
* 4 6 15 3|INF INF 0 INF 5 INF
* 5 6 4 4|INF INF 4 0 13 15
* 5|INF INF INF INF 0 4
* 6|INF INF INF INF INF 0
* |
* 出发点
*
* dis[i]=e[1][i]
* 0---1---2---3---4---5---6---->到达点
* 0 3 12 INF INF INF
* book[7]
* 0---1---2---3---4---5---6---->到达点
* 1 0 0 0 0 0
*/
//输出最终的结果
for(i=1;i<=n;i++)
printf("%d ",dis[i]);
getchar();
getchar();
return 0;
}