最短路径算法-Dijkstra 2 zz

算法流程

在以下说明中,s为源,w[u,v]为点u和v之间的边的长度,结果保存在dist[]

  1. 初始化:源的距离dist[s]设为0,其他的点距离设为无穷大,同时把所有的点的状态设为没有扩展过。
  2. 循环n-1次:
    1. 在没有扩展过的点中取一距离最小的点u,并将其状态设为已扩展。
    2. 对于每个与u相邻的点v,执行Relax(u,v),也就是说,如果dist[u]+w[u,v]<dist[v],那么把dist[v]更新成更短的距离dist[u]+w[u,v]。此时到点v的最短路径上,前一个节点即为u。
  3. 结束。此时对于任意的u,dist[u]就是s到u的距离。

 

 算法实现

 

 直接实现

最简单的实现方法就是,在每次循环中,再用一个循环找距离最短的点,然后用任意的方法更新与其相邻的边,时间复杂度显然为O(n2)

对于空间复杂度:如果只要求出距离,只要n的附加空间保存距离就可以了(距离小于当前距离的是已访问的节点,对于距离相等的情况可以比较编号或是特殊处理一下)。如果要求出路径则需要另外V的空间保存前一个节点,总共需要2n的空间。

 

 二叉堆实现

使用二叉堆(Binary Heap)来保存没有扩展过的点的距离并维护其最小值,并在访问每条边的时候更新,可以把时间复杂度变成O(n+mlogn)。

当边数远小于点数的平方时,这种算法相对来说有很好的效果。但是当m=O(n2)时(有时候表现为不限制边的条数),用二叉堆的优化反倒会更慢。因为此时的复杂度是O(n+n2logn),大于不用堆的实现的O(n2)的复杂度。

另外此时要用邻接表保存边,使得扩展边的总复杂度为O(m),否则复杂度不会减小。

空间复杂度:这种算法需要一个二叉堆,及其反向指针,另外还要保存距离,所以所用空间为3n。如果保存路径则为4n。

具体思路:先将所有的点插入堆,并将值赋为极大值(maxint/maxlongint),将原点赋值为0,通过松弛技术(relax)进行更新以及设定为扩展。

 菲波那契堆实现

  • 用类似的方法,使用Fibonacci Heap可以将复杂度降到O(m+nlogn),但实现比较麻烦。因此不宜在时间较短的信息学竞赛中使用。详见Fibonacci堆

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值