算法导论-第24章 Dijkstra算法

本文介绍了Dijkstra算法解决有向图单源最短路径问题的原理,强调边权重非负值的重要性。通过维护集合Q和不断松弛操作,逐步找到源点到所有点的最短路径。讨论了两种实现方式,一种使用数组,总运行时间为O(V^2),另一种使用自定义最小堆的优先队列,总运行时间为O((E+V)lgV)。同时,提供了带句柄的数组建最小优先队列的代码片段,并对比了Dijkstra算法与广度优先搜索的联系。
摘要由CSDN通过智能技术生成

           Dikstra算法解决的是有向图上单源最短路径问题(无向图可以看成有相反的两条有向边),且要求边的权重都是非负值(如果有负权,已经确定的最短路径到v点有可能会被右面发现的点有条负权值的边到v点而导致v点的最短路径不成立)。

           算法导论用了很多引理,性质来证明Dijstra算法的正确性,这里不说了,也表达不明白,只说我理解的过程。

           有一个图G( V,E) ,选定一个源点s,维护一个集合Q=V-s,  Q中点有一个d值表示此时从s到该点的已知距离,s.d=0 ;初始化都为正无穷,表明不可达。然后对s点所连接的点(设为点集M)进行松弛操作,就是设点m属于M,

           m.d > s.d+ w(s,m) 则更新 m.d=s.d+w(s,m)  将其慢慢收敛。

  Q中的点能够松弛的松弛完之后,取出此时d值最小的点的,把它看成上面的s点,对其所连接点的进行松弛操作,然后再取点,重复直到Q集合为空。s点到所有点的最短路径就找到了。

              再来说说实现的问题:

  

    1.Q集合用数组来实现,我在实现的时候Q数组存在的是对应点的d值,如果这个点已经被取出则变为1;这样所有的开销都在去最小值上了,因为每次都要扫描整个数组。取点要V次,一次扫描O(V) ,所以总运行时间O(V^2);

   2.Q集合用优先队列实现,但是因为要有decrease-key操作,所以貌似不能用标准库的优先队列。所以只能自己实现一个最小堆的优先队列。因为松弛的时候是找到点,然后又要去更改Q中的对应点的d值,然后在进行调整,所以要有互相指向的句柄。

        取点V次,每次Extract-min花费O(lgV)

       decrease-key E次    ,每次花费 O(lgV)

 总花费           O( (E+V)lgV )


        数组方法的时候,代码不贴出来来了,带句柄的数组建最小优先队列的方法我贴出来,其实句柄就是一个指向元素在数组堆中的位置,因为要建堆,维护堆,取出最小值等操作会因为位置变化,所以要在几个操作里面更新句柄。

    Dijkstra.cpp

 

#include<iostream>
#include<fstream>
#include<queue>
#include"MiniPriorityQueu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值