Dijkstra算法

Dijkstra是解决无负权边无负环的带权图中单源最短路径问题的经典算法。它的大致过程是:以起点为中心,每次取最轻(最短)的一个顶点,更新其相邻结点的最小距离——其实就是运用了贪心思想(简单地说就是每次选取局部最优解),向外层层拓展,直至找遍起点到其他点的最短距离。下面给出算法的流程:

设源点为s,且从s到其他所有顶点的边权均已确定,设集合S初始时为空集;设dist数组,dist[i]表示s到i的最短距离,且dist数组初始值设为s到各点的边权;每次选取一个点u∈(V-S)(即V集合中满足不在S集合中的元素),使得dist[u]为(V-S)中所有点最小dist值;将u加入S,然后枚举u相邻的点,并更新其相邻的点的dist值(对u的所有出边进行松弛——此操作详见代码分析)。

显然,每个顶点只能入集合S一次,所以上述操作最多重复|V|次,又因为对于S中的每个顶点要枚举它相邻的所有结点,即最多松弛|V|次,设n为点数,故Dijkstra算法的时间复杂度为O(n^2);用邻接矩阵存储图,空间复杂度亦为O(n^2)。

算法适用范围:

1、单源最短路径问题;

2、Dijkstra算法要求图G无负权边,即对于任意(u,v)∈E,要求有ω(u,v)>=0;否则,对贪心策略的顶点选择会有影响;

证明:最短路径问题运用了贪心思想,即保证当前dist数组存储的是局部最优解。亦即是说,dist数组满足min(dist[i])(i=1,2,3,..,|V|),是当前最优值。在图中边权非负的情况下,图满足上述性质,而存在负权边时则不满足,因为有可能从一个较大的dist值更新能得到一个比当前min(dist[i])(i=1,2,3,..,|V|)更优的值。

3、Dijkstra算法要求图G无负环,单源最短路问题对于有负环的图是无解的,但Dijkstra算法不能检测出负环。

贴上部分代码:

 

(C++ Code)

1   void Dijkstra(int s,int n)

//s为源点,n为点数

2   {

3      memset(dist,100,sizeof(dist)); 

4      memset(t,false,sizeof(t));

//t数组用于判断点是否在集合S中,若在,则t[i]=true;

5      for (int i=1;i<=n;i++)

6          dist[i]=map[now][I];

//初始化dist数组

7      dist[s]=0;

8      t[s]=true;

9      for (int i=1;i<n;i++)

10     {

11         int min=100;

12         for (int j=1;j<=n;j++)

13            if (!t[j]&&dist[j]<min)

14            {

15                min=dist[j];

16                k=j;

17            }

18         t[k]=true;

           //将最近(轻)的点加入集合S中

19         for (int j=1;j<=n;j++)

20            if(!t[j]&&dist[k]+map[k,j]<dist[j])

21                dist[j]=dist[k]+map[k,j];

//以上为松弛过程,松弛边的操作其实就是更新当前k相邻点的dist值

22     }

23  }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值