Dijkstra

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,比如数据结构、图论、运筹学等。

   
1、算法思想
   令G = (V,E)为一个带权有向图,把图中的顶点集合V分成两组,第一组为已求出最短路径的顶点集合S(初始时S中只有源节点,以后每求得一条最短路径,就将它对应的顶点加入到集合S中,直到全部顶点都加入到S中);第二组是未确定最短路径的顶点集合U。在加入过程中,总保持从源节点v到S中各顶点的最短路径长度不大于从源节点v到U中任何顶点的最短路径长度。
 
2、算法步骤
   (1)初始化时,S只含有源节点;
   (2)从U中选取一个距离v最小的顶点k加入S中(该选定的距离就是v到k的最短路径长度);
   (3)以k为新考虑的中间点,修改U中各顶点的距离;若从源节点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值是顶点k的距离加上k到u的距离;
   (4)重复步骤(2)和(3),直到所有顶点都包含在S中。
   具体图例与算法执行步骤:(就从A开始,到各节点的最短路径)。

1.       迪杰斯特拉算法简介

 迪杰斯特拉(dijkstra)算法是典型的用来解决最短路径的算法,也是很多教程中的范例,由荷兰计算机科学家狄克斯特拉于1959年提出,用来求得从起始点到其他所有点最短路径。该算法采用了贪心的思想,每次都查找与该点距离最近的点,也因为这样,它不能用来解决存在负权边的图。解决的问题大多是这样的:有一个无向图G(V,E),边E[i]的权值为W[i],找出V[0]V[i]的最短路径。

 

3.     迪杰斯特拉算法的原理

首先,引入一个辅助向量D,它的每个分量D[i]表示当前所找到的 Dijkstra算法运行动画过程 Dijkstra算法运行动画过程从起始点(即源点)到其它每个顶点的长度。例如,D[3] = 2表示从起始点到顶点3的路径相对最小长度为2。这里强调相对就是说在算法执行过程中D的值是在不断逼近最终结果但在过程中不一定就等于长度。

D的初始状态为:若从v v[i]有弧(即从vv[i]存在连接边),则D[i]为弧上的权值(即为从vv[i]的边的权值);否则置D[i]。显然,长度为 D[j]= Min{ D |v[i]V } 的路径就是从v出发到顶点v[j]的长度最短的一条路径,此路径为(v,v[j])

那么,下一条长度次短的是哪一条呢?也就是找到从源点v到下一个顶点的最短路径长度所对应的顶点,且这条最短路径长度仅次于从源点v到顶点v[j]的最短路径长度。 假设该次短路径的终点是v[k],则可想而知,这条路径要么是(v,v[k]),或者是(v,v[j],v[k])。它的长度或者是从vv[k]的弧上的权值,或者是D[j]加上从v[j]v[k]的弧上的权值。

一般情况下,假设S为已求得的从源点v出发的最短路径长度的顶点的集合,则可证明:下一条次最短路径(设其终点为x)要么是弧(v,x),或者是从源点v出发的中间只经过S中的顶点而最后到达顶点的路径。因此,下一条长度次短的的最短路径长度必是D[j]= Min{ D[i] |v[i]V-S },其中D 要么是弧( v,v[i])上的权值,或者是D[i]( v[k]S)和弧(v[k] ,v[i] )上的权值之和。

 

3.     迪杰斯特拉算法的实现过程

先取一点v[0]作为起始点,初始化dis[i],d[i]的值为v[0]到其余点v[i]的距离w[0][i],如果直接相邻初始化为权值,否则初始化为无限大;

v[0]标记,vis[0] = 1(vis一开始初始化为0)

找寻与v[0]相邻的最近点v[k],将v[k]点记录下来,v[k]v[0]的距离记为min

v[k]标记,vis[k]=1

查询并比较,让dis[j]min+w[k][j]进行比较,判断是直接v[0]连接v[j]短,还是经过v[k]连接v[j]更短,即dis[j]=MIN(dis[j],min+w[k][j])

继续重复步骤与步骤,知道找出所有点为止。

 4.    迪杰斯特拉的实现代码(C/C++

 1intdijkstra(int n)

 2 {

 3//初始化v[0]到v[i]的距离

 4for(inti=1;i<=n;i++)

 5         dis[i] = w[0][i];                                      

 6     vis[0]=1;//标记v[0]

 7for(inti = 1; i<= n; i++)

 8     {

 9//查找最近点

10int min = INF,k = 0;

11for(int j = 0; j<= n; j++)

12if(!vis[w] && dis[j] < min)

13                 min = dis[w],k = j;

14        vis[k] = 1;//标记查找到的最近点

15//判断是直接v[0]连接v[j]短,还是经过v[k]连接v[j]更短

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

17if(!vis[j] &&min+w[k][j] < dis[j])

18                 d[j] = min+w[k][j];

19     }

20return dis[j];

21 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值