单源最短路径Dijkstra算法:只能处理正权边,可以有环

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之外的距离最小值点作为搜索点。

猜你喜欢

转载自blog.csdn.net/qq_33726635/article/details/106521073