关于最小路径的算法(Dijkstra算法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33120763/article/details/78554600

关于最小路径的算法(Dijkstra算法)

*注:这里我只研究算法,不研究实现* _(其实是本人太菜)

**先定义概念:Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他 *所有节点* 的最短路径(注意是可以求出到所有节点的最短路径)。**

主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。(我们通过对路线长度的计算,得到每个顶点的权重,权重越小,代表路径越短。)


    需要两个集合来存储图中的顶点:
  • S集合初始只包含起始顶点,每算出来一条最短路径,就将新路径的终点加入集合中。
  • U集合为未确定最短路径的顶点的集合,初始包含图中除了初始顶点外的所有点。



    算法流程:

    ①->

      将初始点 v 存入 S 中,指定其权值为 0 ,设置 v 为中间点;
      将图中的除了v的所有点存入 U 中,暂时不指定它们的权值;

    ②->
      计算 :

     Q =  S中间点的权值  + S中间点到U中各点的距离;
     if( S中间点不和U中的点连接){
         设置该点的 Q 为 无穷大;
     }
     //此时所有点都会有权值
     if ( U中的各点还没有指定权值 ) {
        指定该点的权值为 Q;
     } else ( U中的各点已经有了权值 ){ 
        if ( Q < 该点的权值 ){
            将该点的权值变为Q;
        } else ( Q > 该点的权值 ){
            不做动作;
        }
     }
    
    ③->
      比较U中的所有点的权值,取出权值最小的那个点(这里暂时指定其为 k),将其放入S中,S就变为
    此时我们的图是这样的
         v -> a  
         v -> b
         a -> b
    
    第一次求最短路径 
        得到 v - b , S中是 < v , b >
        此时,虽然a没有放入S中,但是它有了权值,正确的说,是V中所有点都有了权值。a的权值为 3, b的权值为2.
    
    第二次求最短路径
    
        因为 Q = b->a的距离 + b 的权值  = 4  >  a的权值 Q= 3 (也就是第一次求得的权值),
        所以 a 的权值不变。
    
        因为 此时U中最小的权值不是本次计算后变化得到的,而是之前计算得到的权值
        所以 本次求得的最短路径并不是 v -> b -> a 而是 v -> a
        还是将权值最小的a放入S,并设置a 为新的中间点,并添加一条记录:
            起始点: v ,目的地:a  ,最短路径: v -> a
    
    
        如果是   Q = b->a的距离 + b 的权值   <  a的权值 
        将 a 的权值修改为 (b -> a的距离 + b 的权值),并将a放入X中,设置中间点为a,并添加一条记录:
            起始点: v ,目的地:a  ,最短路径: v -> b -> a



    ④->
      转到②继续执行,直到U为空




    如果要知道所有的最短路径,就得在每一次计算权重的时候,给这个顶点附加一条信息,来说明这次的权值是 哪几条路径 相加得到的。 
    比如:我们的附加信息为: a点的最短路径 = a之前的那条最短路径(用路径的终点表示) + a
    通过递归:
    a 之前的那条最短路径 = a 之前的之前的那条最短路径 + 之前的最短路径的终点 + a
    a 之前的之前的那条最短路径 = a 之前的之前的之前的那条最短路径 + 之前的之前的最短路径的终点 + a

    直到找到起点
    然后我们就能找到每条最短路径

    猜你喜欢

    转载自blog.csdn.net/qq_33120763/article/details/78554600