最短路径 Dijkstra算法

小博今天又给大家更新了,最近学习过程中在最短路径问题上被两个比较……我们暂且认定比较恶心的算法难倒了好一会,不过最后还是攻克了,在这里小博写下自己的心得和大家分享一下

**最短路径:**网路中两个不同顶点之间的所有路径中边的权值之和最小的那一条
这条路径两点之间的最短路径(shortest past)
第一个顶点为源点(source)
最后一个点为终点(destination)
问题分类:
1 单源最短路径问题:从固定源点出发,求其到所有其他顶点的最短路径(Dijkstra算法)
2 多源最短路径问题:求任意两个顶点间的最短路径(Floyd算法)
以上都是一些基本概念之类的问题 接下来看重点

1 首先介绍一下Dijkstra算法(有些总结性的东西我是借照书上的总结,不过具体实现方式我会给大家展示清楚的)
该算法设置一个集合S记录以求得的最短路径顶点,用一个数组s[]来实现,初始化为0,当s[i]=1,则表示将定点vi放到S中,但是记住初始化时将v0放到S中。
此外构造两个辅助数组:
dist[]:记录从源点V0到其他各个顶点当前最短路径的长度,dist[i]的初值为arcs[V0][i]。其实一般情况大家为了好写都写成<V0,Vi>
path[]:path[i]表示从源点到顶点i之间最短路径的前驱结点。这个要怎么理解呢,就是加入你V0 ->V1-> V2,然后V0到V1记作path[1],在算法结束时,可以根据path[1]追溯的源点V0到V1的最短路径。
假设从顶点0出发,即V0=0,集合S最初包含0个顶点,邻接矩阵arcs表示带权图,arcs[i][j]表示有向边<i,j>的权值,如果不存在记为∞。
在这里插入图片描述
就比如这个图 <V0,V1>记为10;而<V0,V2>记为∞
具体操作
1)初始化:集合S初始化为0。(解释一下集合S表示{源点+已经确定了最短路径的源点Vi})。
2)从顶点集合V-S中选出来Vj,满足dist[j]=Min{dist[i] | Vi∈V-S},解释一下Vj表示当前求得的一条从Vo出发最短路径的终点,则现在S=S∪{j}。
3)修改从Vo出发到集合V-S上任意一点Vk可达的最短路径长度:如果dist[j]+arcs[j][k]<dist[k],则令dist[k]=dist[j]+arcs[j][k]。
这个要怎么解释呢,话不多说,直接上图
在这里插入图片描述
dist[j]+arcs[j][k]<dist[k],则令dist[k]=dist[j]+arcs[j][k]。
10+20=30<35 所以dist[k]=30 这样解释就很清楚了。
4)重复2 3操作共n-1次(为什么是n-1呢?不要忘了Vo是源点哦)

基本到此算法思想就解释清楚了,现在我们用一个例子展示一下
给出这样一个图
在这里插入图片描述
给出这样一个无向图,按照Dijkstra算法,写出从顶点1到其他各个顶点的最短路径和最短路径长度

接下里小博详细的介绍一下这道题的思路
首先先把除了1结点之外的结点全部写到一个表格里面,如下图
在这里插入图片描述
接着进行第一趟:写出从V1到其余各顶点的权值,请注意,是直接路径,如果不是直接路径,用∞表示,如下图
我们发现,dist[2]=7为最小,所以将V2置入S中,所以顶点1到顶点2最短路径<V1,V2>,其长度为7
在这里插入图片描述
接着进行第二趟:写出从V1经过V2到其余各顶点的权值,值得注意一点,比如<V1,V2,V3>为17,但是发现<V1,V3>=11,则我们取最短路径,不要经过V2,也就是最小值!!!同时经过V2到达其余各点,其余点必须与V2有直接联系,不然依然置为∞!!!最后将V3置入S中。如下图所示
我们发现最短路径为<V1,V3>,其长度为11
在这里插入图片描述
接着进行第三趟:写出从V1经过V3到其余各顶点的权值,值得注意一点,比如<V1,V2,V4>为16,但是发现<V1,V3,V4>=16,最后将V4置入S中。其实个人觉得这两条路径都可以选取,这也是小博疑惑的点,如果有大佬看到,恳请斧正。如下图所示
在这里插入图片描述
接着进行第四趟:写出从V1经过V4到其余各顶点的权值,值得注意一点,比如<V1,V3,V5>为18,为最短路径,最后将V5置入S中。如下图所示
在这里插入图片描述
最后进行第五趟:写出从V1经过V5到其余各顶点的权值,如<V1,V3,V6>为19,为最短路径,最后将V6置入S中。如下图所示
在这里插入图片描述
到此整个过程结束,从顶点1到其余各点的最短路径如下图所示:
在这里插入图片描述

最后贴出来代码

void Dijkstra(Vertex s)
{
	while (1){
		v=未收录顶点中dist最小;
		if(这样的V不存在)
			break;
		collected[V]=true;
		for(V的每个邻接点W)
			if(collected[W]==false)
				if(dist[V]+E<v,w><dist[W])
				{
					dist[W]=dist[V]+E<v,w>;
					path[W]=V;
				}
	}
}

从源点到某一特定顶点的最短路径这个问题和求解源点到其他所有顶点的最短路径一样复杂,时间复杂度为O(|VV|)。如果要找出所有结点对之间的最短距离,则需要对每个结点运行一次Dijstra算法,其时间复杂度为O(|VV*V|)。

到此应该大功告成,下周我会继续更新Floyd算法的过程。
还有6个月就要考试了,在跨考的路上走了3个多月了,突然最近好累,经常会感觉到很迷茫,但是,既然选择了,就做下去吧,你不做还有很多人做,世上永远不缺人才,对吗? Do it,or die. 大白加油!!!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值