最短路径-迪杰斯特拉(Dijkstra)算法

这是一个按路径长度递增的次序产生最短路径的算法。它的思路大体是这样的。

核心思想是通过维护一个集合S,其中包含已经求出最短路径的顶点,以及一个距离数组dist,记录起始顶点到每个顶点的当前最短距离。在每一轮迭代中,选择距离数组中距离最小的顶点v,将其加入集合S,并更新起始顶点到其邻接顶点的距离。具体步骤如下:

  1. 初始化距离数组dist,起始顶点到自身的距离为0,其他顶点的距离初始化为无穷大。
  2. 选择起始顶点作为当前顶点v。
  3. 更新v的邻接顶点的距离:遍历v的邻接顶点u,计算起始顶点到u的距离,若小于dist[u],则更新dist[u]为新的最短距离。
  4. 从未加入集合S的顶点中选择距离最小的顶点作为新的当前顶点v,重复步骤3。
  5. 重复步骤3和步骤4,直到所有顶点都被纳入集合S。
  6. 最终得到起始顶点到所有顶点的最短距离。


如果还是不太明白,不要紧,现在我们来看代码,从代码的模拟运行中,再次去理解它的思想。

#define  MAXVEX  9
#define  INFINITY  65535
typedef  int  
/*  用于存储最短路径下标的数组  */
Patharc[MAXVEX];        
typedef  int  
/*  用于存储到各点最短路径的权值和  */
ShortPathTable[MAXVEX]; 
/*  Dijkstra算法,求有向网G的v0顶点到其余顶点v最短路径P[v]及带权长度D[v]  */
/*  P[v]的值为前驱顶点下标,D[v]表示v0到v的最短路径长度和。  */
void  ShortestPath_Dijkstra(MGraph  G,  int  v0,  Patharc  *P,  ShortPathTable  *D)
{
int  v,  w,  k,  min;
/*  final[w]=1表示求得顶点v0至vw的最短路径  */
int  final[MAXVEX];   
/*  初始化数据  */
for  (v  =  0;  v  <  G.numVertexes;  v++)  
{
/*  全部顶点初始化为未知最短路径状态  */
final[v]  =  0;       
/*  将与v0点有连线的顶点加上权值  */
(*D)[v]  =  G.arc[v0][v];                   
/*  初始化路径数组P为-1  */
(*P)[v]  =  -1;       
}
/*  v0至v0路径为0  */
(*D)[v0]  =  0;       
/*  v0至v0不需要求路径  */
final[v0]  =  1;      
/*  开始主循环,每次求得v0到某个v顶点的最短路径  */
for  (v  =  1;  v  <  G.numVertexes;  v++)
{
/*  当前所知离v0顶点的最近距离  */
min=INFINITY;         
/*  寻找离v0最近的顶点  */
for  (w  =  0;  w  <  G.numVertexes;  w++)  
{
if  (!final[w]  &&  (*D)[w]  <  min)
{
k=w;
/*  w顶点离v0顶点更近  */
min  =  (*D)[w];      
}
}
/*  将目前找到的最近的顶点置为1  */
final[k]  =  1;       
/*  修正当前最短路径及距离  */
for  (w  =  0;  w  <  G.numVertexes;  w++)  
{      
/*  如果经过v顶点的路径比现在这条路径的长度短的话  */
if  (!final[w]  &&  (min  +  G.arc[k][w]  <  (*D)[w]))
{                     
/*  说明找到了更短的路径,修改D[w]和P[w]  */
/*  修改当前路径长度  */
(*D)[w]  =  min  +  G.arc[k][w];        
(*P)[w]=k;
}}}}

也就是说,我们通过迪杰斯特拉(Dijkstra)算法解决了从某个源点到其余各顶点的最短路径问题。从循环嵌套可以很容易得到此算法的时间复杂度为O(n2),尽管有同学觉得,可不可以只找到从源点到某一个特定终点的最短路径,其实这个问题和求源点到其他所有顶点的最短路径一样复杂,时间复杂度依然是O(n2)。
这就好比,你吃了七个包子终于算是吃饱了,就感觉很不划算,前六个包子白吃了,应该直接吃第七个包子,于是你就去寻找可以吃一个就能饱肚子的包子,能够满足你的要求最终结果只能有一个,那就是用七个包子的面粉和馅做的一个大包子。这种只关注结果而忽略过程的思想是非常不可取的。
可如果我们还需要知道如v3到v5、v1到v7这样的任一顶点到其余所有顶点的最短路径怎么办呢?此时简单的办法就是对每个顶点当作源点运行一次迪杰斯特拉(Dijkstra)算法,等于在原有算法的基础上,再来一次循环,此时整个算法的时间复杂度就成了O(n3)。
对此,我们现在再来介绍另一个求最短路径的算法——弗洛伊德(Floyd),它求所有顶点到所有顶点的时间复杂度也是O(n3),但其算法非常简洁优雅,能让人感觉到智慧的无限魅力。好了,让我们就一同来欣赏和学习它吧

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值