(图)最短路径的求法之迪杰斯特拉算法

对于网图而言,最短路径指两顶点之间经过的边上权值和最少的路径,并且路径上的第一个顶点是源点,最后一个顶点是 终点。

迪杰斯特拉dijkstra算法: 

其本质是一种贪婪算法

也是最经典的单源最短路径算法




假设源点是V1,终点是V8,求其最短路径。

我们先求V1到V2 V4 V3哪条路径最短,答案是到V2最短。由于V2与V4 V5连线,V2->V5=7  V2->V4=1  故选择V4

于是再求V1到V4的最短路径,V1->V2->V4=4,    V1->V4=5

故V1->V2->V4是最短距离的路程

V4与V3 V6 V7连线(V5排除)而后再重复比较路径

算法简单来说就是

一步一步地求出它们之间的顶点的最短路径,过程中是基于已经求出的最短路径的基础上,求得更远顶点的最短路径

算法代码如下:

#define MAX 9    				//假设最大顶点数为9
#define INFINITY  65535 
typedef int Path[MAX];  	   	//存储最短路径顶点下标
typedef int ShortPath[MAX]; 	//存储到各点最短路径的权值和

/*求有向网G的V0顶点到其余顶点V的最短路径P[V]以及带权长度D[V]
P[V]的值为前驱顶点的下标,D[V]表示V0到V的最短路径长度和*/

/*需要使用邻接矩阵*/ 
 
void ShortesPath(MGraph G,int v0,Path *p,ShortPath *D)  //v0定义为0 
{
	int v,w,k,min;
	int final[MAX];     	//标志数组,final[x]=1时表示已经求得V0到VX顶点的最短路径
	/*初始化*/ 
	for(v=0;v<G.numVertexes;v++)
	{
		final[v]=0;          	//均为0表示所有点都没有求得最短路径 
		(*D)[v]=G.arc[v0][v];	//将与V0点有连线的顶点加权值,即将第V0行的邻接矩阵数据读入到D数组 
		(*p)[v]=0;				//p数组全为0,表示目前没有路径 
	}
	(*D)[v0]=0;				//V0到自身的权值和为0 
	final[v0]=1; 			//V0算是已经求得最短路径(此时只有v0本身)
	
	/*开始主循环,每次求出V0到某个顶点V的最短路径*/
	for(v=1;v<G.numVertexes;v++)    //从1开始 
	{
		min=INFINITY;
		for(w=0;w<G.numVertexes;v++)
		{
			if(!final[w]&&(*D)[w]<min)   //顶点未加入最短路径且权值小于无穷(即与V0存在连线) 
				{
					k=w;
					min=(*D)[w];    //w顶点离V0更近 
				}	 
					
		}
		final[k]=1;           //表示已求得最短
		
		/*重要循环*/ 
		for(w=0;w<G.numVertexes;w++)       //修正最短路径和距离 
		{
			if(!final[w]&&(min+G.arc[k][w]<(*D)[w]))	 
			{
				(*D)[w]=min+G.arc[k][w];
				(*p)[w]=k;
			}	
		}		
	} 	
} 

代码解析被系统吃掉了,暂时不愿意再打一遍了

简单来说重要循环的作用是在找到V0和V1的最短路径的基础上对与V1有连线的其他顶点的边上权值进行计算得到最小权值和

有空再详述


算法的时间复杂度:

由于嵌套循环的存在,时间复杂度为O(n²)。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值