一、概括:贪心策略
Dijktra最短路径算法采用的是一种贪心的策略,通过逐次地找到各点距起点的最短路径并由该路径更新该顶点出度的路径,进而使图中所有点距离起点路径最短的算法。
详细推导过程可见:https://blog.csdn.net/qq_35644234/article/details/60870719
二、数据结构:
1.一维数组:
int dist[] :用于保存距离起点最短路径,若与起点不连通则用一个较大的数表示(如16进制的:0x3f3f3f)
int/bool flag[]:用于保存已经得出最短路径的顶点的集合,已得出则为1/true,否则为0/false
char s[] :用于保存图中的顶点名称等,也可以用一个结构体保存。
2.二维数组:
int map[][]:邻接矩阵(二维数组)的形式保存一个图的基本信息,其中权重为初始路径。
三、代码实现:
输入:
总顶点数:n 总边数:m
接下来m 行: 顶点:a 顶点:b 距离:len
输入起点:start
输出:
各顶点据起点的最短距离
dist [ i ]
c/c++混搭语言代码:
注释:输入数据均以1为起点,秉承勤俭节约的中华传统,数组都是以0为起点(其实就是懒得改了)
测试数据:
图片来源:https://blog.csdn.net/qq_35644234/article/details/60870719
6 8
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
5 4 20
5 6 60
1
输出:
1 ->1 : 4144959
1 ->2 : 4144959 //为一个大数,可在输出时改成其他符号如~
1 ->3 : 10
1 ->4 : 50
1 ->5 : 30
1 ->6 : 60
#include<stdio.h>
#include<string.h>
#define MAX 100
#define inf 0x3f3f3f
#define min(a,b) a<b?a:b
int map[MAX][MAX];
bool flag[MAX];
int dist[MAX];
int n,m;//n是顶点数,m为边数
void find_shortest(int start);
int main()
{
int a,b,len;//顶点 顶点 距离
int start;//起点
memset(map,0,sizeof(int)*MAX*MAX);
scanf("%d%d",&n,&m);
while(m--)//获取图信息
{
scanf("%d %d %d",&a,&b,&len);
map[a-1][b-1] = len;//数组以0开始,为方便输入数据以1开始
}
for(int i = 0 ; i<n ; i++)
for(int j = 0 ; j<n ; j++)
if(map[i][j]==0)
map[i][j] = inf;
scanf("%d",&start);//输入起点
find_shortest(start-1);//方便输入数据,start-1
for(int i = 0 ; i<n ; i++)
printf("%d ->%d : %d\n",start,i+1,dist[i]);//方便观察数据i+1.
return 0;
}
void find_shortest(int start)
{
for(int i = 0 ; i<n ; i++)
{
flag[i] = false;
dist[i] = inf;
}
flag[0] = true;
dist[0] = 0;//初始化集合和最短路径
for(int i = 0 ; i<n ; i++)
dist[i] = map[start][i];//将起点各出度赋给最短路径数组
for(int i = 0 ; i<n ; i++)//保证所有与起点连通的顶点都加入集合
{
int min = inf;//保存起点到顶点的距离
int t = start;//保存顶点
for(int j = 0 ; j<n ; j++)//打擂台找集合外距起点最短距离
{
if(!flag[j]&&dist[j]<min)
{
min = dist[j];//记录最短距离
t = j;//记录顶点
}
}
if(t == start)
return ;//没有与起点连通的顶点
flag[t] = true;//将该顶点加入集合
for(int j = 0 ; j<n ; j++)//维护该顶点出度的最短路径
{
if(!flag[j]&&map[t][j]<min)//保证不在集合内且与该顶点连通(出度)
dist[j] = min(dist[j],dist[t]+map[t][j]);
}
}
}