1、算法介绍:
迪杰斯特拉(Dijkstra)又叫狄克斯特拉算法,用于求所有权重边都非负情况下的单源最短路径问题,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
2、伪代码描述:
1、初始化:设d[0]=0,其他d[i]=INF;//INF是一个很大的值,用来替代正无穷
2、循环V次(循环节点集个数次,也可以像图中表示,队列q会pop()V次)
{
在所有未标号结点中,选出d值最小的结点x;(第一次为源点,d为0)
给结点x标记;
对于从x出发的所有边(x,y),更新d[y] = min{d[y], d[x]+w(x,y)
//对所有边松弛,可以不包括到已经标记过的节点的边,因为标记过得节点路径已经最短。
}
3、算法图解:
3.1、节点集合S与Q的变化过程:
3.2、路径查找详细过程:
无向图:
用Dijkstra算法找出以A为起点的单源最短路径步骤如下:
4、C++代码:
#include<stdio.h>
#define INF 0x3f3f3f3f //表示距离正无穷大,用来图的初始化
int map[1010][1010]; //较大的空间用于放图,存放两点间的权值
//假设图已经初始化完成,无连接点权重无穷大
int dis[1010]; //存放各点距起点的距离
int mark[1010]; //标记使用过的点
int v,m; //有v个点,编号为1~v,有m条边
void dijkstra(int s)
{
for(int i=1;i<=v;i++){ //初始化标记数组和距离数组
mark[i]=0; //0表示未使用此点
dis[i]=INF;
}
dis[s]=0; // 源点距离为0
int vir = 0;
int min; // 记录目前距离最短的点
for(int i=1;i<=V;i++){ // 执行V次循环
min = INF; // 每次寻找都要初始化
for(int j = 1;j<=V;j++){ // 寻找当前距离最小的点
if(!mark[j] && dis[j]< min ){ min = dis[j]; vir = j;}
}
mark[vir] = 1; // 标记找到的距离最小点
for(int j = 1;j<=V; j++){ // 对所有连接边进行松弛
if(!mark[j] && dis[j] > dis[vir]+map[vir][j]) ( dis[j] = dis[vir]+map[vir][j] )
}
}
}
参考资料:
1、百度百科——迪科斯彻算法
2、最短路径—Dijkstra算法和Floyd算法
总结:
1、迪杰斯特拉Dijkstra算法只能处理正权边,可以有环。
2、类似于BFS,每一次搜索只搜索与当前节点连接的一层节点;
3、类似于最小生成树的prim算法,每一次搜索的起点都以集合S之外的距离最小值点作为搜索点。