这里写目录标题
1.算法简介
Dijkstra算法又称标号法,用来寻找带权途中的最短路径问题
是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
2.原理
1.找到起始点
任选一个点作为起始点
2.计算起始点第一步
计算起始点第一步能到达的点的距离,并选择这些距离中的最小距离作为到达的点作为中介点
3.以中介点往下计算
以中介点作为点往下进行计算,计算以这个中介点到达下一个点的距离,若计算出的距离小于上次计算的距离,者进行替换,包括上次的步骤路径一起进行替换。若大于上次的距离,则不需要进行替换,并寻找这次起始点经各路径到达每个点的距离中的最短距离
4.重复以上步骤
重复寻找,知道找到全部最短距离为止
2.实际操作
1,选择初始点为点1
2.计算初始点到一步就能到达的点
3.比较:
即比较这一列
4.以得到的红色结果继续寻找并比较
寻找到的结果继续比较
即比较得到的结果与上次的结果,就是比较每一行,并进行替换
比较之后再次比较每列,得到该次的结果
5.重复以上步骤直到找到所有结果
3.总结
通俗而言就是只有两个步骤,就是比较和替换,先比较列,在比较行,找到最小值。每次如此,进行寻找。直到找到全部为止
4.c语言代码
以矩阵输入
#include <stdio.h>
#define INF 1000 //将该值当做等价无穷小
#define Max 50
int main()
{
int jz[Max][Max]; //Max为最大顶点数
int min1[Max]; //min1[i]为源点到顶点i的最短距离
int done[Max]; //done[i]标记顶点i的最短路径是否已求出 done[i] == 1表示已求出
int jd[Max]; //jd[i]表示 起始点通过jd[i]这个点到达i这个点最短路径 <v1,v2,v3>中jd[3]=2
int n,q = 0; //q是已求出最短路径的顶点数目
printf("请输入节点个数:");
scanf("%d", &n);
printf("\n请输入矩阵:\n");
int lj[n]; //lj表示路径
for (int i = 0; i < n; i++) //矩阵的输入
{
for (int j = 0; j < n; j++)
{
scanf("%d",&jz[i][j]);
}
}
done[0] = 1; //起始点不可求到起始点的最短距离,相当于已经求出
jd[0] = 0;
for (int i = 1; i < n; i++) //初始化
{
min1[i] = jz[0][i]; //将起始点到各点的距离录入
jd[i] = 0; //
}
q++; //上面求出一个最短距离点,故此加 1
while (q < n) //n个节点求n-1次
{
int min = INF, a; //初始化值,以供每次循环使用
for (int i = 1; i < n; i++)
{
if (done[i] == 0 && min > min1[i]) //找到距离源点最短的顶点a
{
min = min1[i]; //这个循环是求表中每个列的最小值
a = i;
}
}
done[a] = 1; //表中每列最小值即为到对应点的最小值
q++; //求出最小值后,加一
//实际上是先算下面这一个循环,但第一个循环在初始化的时候就相当与进行了
for (int i = 1; i < n; i++)
{
if (done[i] == 0 && min1[a] + jz[a][i] < min1[i]) //计算表中下一列的各个数值,若比上次的小,则更新
{
min1[i] = min1[a] + jz[a][i]; //替换成更小的值
jd[i] = a; //表示到达 i节点的前一个点,每次路径比前一个小时,更新
}
}
}
printf("\n\n");
for (int i = 1; i < n; i++)
{
if (min1[i] == INF)
{
printf("点 1 到点 %d 没有最短路径\n", i);
}
else
{
printf("点 1 到点 %d 有长为 %d 的最短路径:",i+1,min1[i]);
int b = i, c= 0; //初始化值,用于每次循环
lj[c] = b; //倒序存放,最后一个数字存放起始点
//找路径
while (1)
{
lj[c + 1] = jd[lj[c]]; //每向后一位找到在最短路径上该点的前一位,i点的前一位为jd[i]
if (lj[c + 1] == 0) //每次前一位录入路径中欧判断,起始点是0,所与当向后找到最后一位是0,结束
{
break;
}
c++; //每次循环向后一位,进行加一
}
//打印输出
for (int j = c + 1; j > 0; j--)
{
printf("%d->", lj[j]+1);
}
printf("%d\n", lj[0]+1);
}
}
}