单源到任意点最短路径(Dijkstra算法)举例

以a为源点,求a到其他各点的最短路径、最短路径距离。
基本思想:
1. 源点一开始就被收录到集合S{ }中,其他顶点按照距离的递增原则一一被收录;
2. 每收录一个顶点v就更新一次v所相邻但未被收录的最小距离以及路径;
3. 直到所有点都被收录,算法结束。


初始化:
1. a被收录,a的最短距离为0,与a相邻的各点最短路径设为相连的边长权重,其余各点的距离为正无穷大∞;并且设置各点的最短路径,没有最短路径长度的点可设为-1
  • 定义dist[ ], 则dist[a]=0, dist[b]=7, dist[e]=14, dist[f]=9, dist[c]=∞, dist[d]=∞
  • 定义path[ ],则path[a]=-1, path[b]=a, path[f]=a, path[e]=a, path[d]=-1, path[c]=-1
  • 注意:a, b, c...是具体的整数,可表示为顶点下标
  •  以上设置的dist[ ]和path[ ]都是临时的,在算法中可能会被不断更新,直到最后为最短路径以及长度

2. 从未收录的顶点中找到距离值最小dist的那个V,然后更新该点所相邻但未被收录点的距离以及路径path(如果该收录的点没有使得相邻点距离变得更小,则不更新距离值和路径)
  • 找到dist[ ]最小值,收录b;
  • 其中f值dist[b]+dist<b,f>=7+10>9, 不被更新
  • c点 dist[b]+dist<b,c>=7+15<∞,被更新dist[c]=dist[b]+dist<b,c>,path[c]=b

3. 重复步骤二,收录f(因为此时未收录点中dist[f]最小,看圆圈里的数字),更新e和c,此时的e、c最短距离都可以经过f点的路径变得更小。

4. 重复步骤2,收录e,更新d和对应的路径

5.重复步骤2,收录c或d(此时剩余的d和c的dist都一样,选任意一个)
6.最后收录d或c,算法结束,源点a到每个点的最短距离和路径都被计算出来


dist[V]就是源点到任意点V的最短距离
回溯path[V],path[path[V]],path[path[path[V]]]......直到path[a]=-1可以用堆栈顺序地将源点到任意点V的路径输出


时间复杂度分析:
方法一:如果每次收录最小dist是遍历所有的未收录V,则共遍历|V|次,|V|个点被遍历|V|遍则O(|V|^2),而每条边在收录过程中被访问一次O(|E|),加起来就是 O(|V|^2+|E| )。
方法二:如果我们把dist储存到“最小堆”里面(最小堆的建立最小时间复杂度是O(|V|),即线性时间),每次取出最小值,将最小堆调整一次O(log|V|),而且每次取出这个最小值之后要更新有相邻边顶点的值,即对最小堆里面个别值进行更新并且调整O(log|V|),综合起来就是 O(|V|log|V|+|E|log|V|)

分析:对于稠密图来说,O(|E|)=O(|V|^2),则用方法一比较好;对于稀疏图来说,O(|E|)=O(|V|)用方法二比较好。以上这两种方法的区别就在于,第一种方法最大消耗时间在检索最小距离点的时候是遍历过程,而在更新时候只是需要搜索部分边(所以边一般只遍历了线性时间),而第二种方法最大消耗时间在于更新相邻边的顶点值,而且要更新该顶点在最小堆里面的位置,一共是:边数×更新时间=|E|log|V|。

主要参考:MOOC课程-浙江大学陈越-数据结构与算法


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值