zoukankan      html  css  js  c++  java
  • 最短路径算法

    一、单源点最短路径问题 :

    问题描述:给定带权有向图G=(V, E)和源点v∈V,求从v到G中其余各顶点的最短路径。

    迪杰斯特拉(Dijkstra)提出了一个按路径长度递增的次序产生最短路径的算法。

    Dijkstra算法

    基本思想:设置一个集合S存放已经找到最短路径的顶点,S的初始状态只包含源点v,对vi∈V-S,假设从源点v到vi的有向边为最短路径。以后每求得一条最短路径v, …, vk,就将vk加入集合S中,并将路径v, …, vk , vi与原来的假设相比较,取路径长度较小者为最短路径。重复上述过程,直到集合V中全部顶点加入到集合S中。

      下一条最短路径(设其终点为vi)或者是弧(v0,vi),或者是中间经过S中的顶点而最后到达顶点vi的路径。

      

    示例

    算法步骤:

    ① 令S={Vs} ,用带权的邻接矩阵表示有向图,对图中每个顶点Vi按以下原则置初值:

    ② 选择一个顶点Vj ,使得:dist[j]=Min{ dist[k]| Vk∈V-S },Vj就是求得的下一条最短路径终点,将Vj 并入到S中,即S=S∪{Vj} 。

    ③ 对V-S中的每个顶点Vk ,修改dist[k],方法是:

      若dist[j]+Wjk<dist[k],则修改为:dist[k]=dist[j]+Wjk ("Vk∈V-S )

    ④ 重复②,③,直到S=V为止。

    算法实现

     1 void ShortestPath_DIJ(MGraph G,int v0,PathMatrix &P,ShortPathTable &D)
     2 
     3 { 
     4 
     5     // 用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]
     6 
     7     // 及其带权长度D[v]。
     8 
     9     // 若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。
    10 
    11     // final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。
    12 
    13     int i=0,j, v,w,min;
    14 
    15     bool final[MAX_VERTEX_NUM];
    16 
    17     for (v=0; v<G.vexnum; ++v) 
    18 
    19     {
    20 
    21         final[v] = FALSE;  
    22 
    23         D[v] = G.arcs[v0][v].adj;
    24 
    25         for (w=0; w<G.vexnum; ++w)  
    26 
    27             P[v][w] = FALSE;  // 设空路径
    28 
    29         if (D[v] < INFINITY) { P[v][v0] = TRUE;  P[v][v] = TRUE; }
    30 
    31     }
    32 
    33     D[v0] = 0;  final[v0] = TRUE;        // 初始化,v0顶点属于S集
    34 
    35     //--- 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集 ---
    36 
    37     for (i=1; i<G.vexnum; ++i)          // 其余G.vexnum-1个顶点
    38 
    39     {         
    40 
    41         min = INFINITY;                    // 当前所知离v0顶点的最近距离
    42 
    43         for (w=0; w<G.vexnum; ++w)
    44 
    45             if (!final[w])                           // w顶点在V-S中
    46 
    47                 if (D[w]<min) { v = w;  min = D[w]; }  // w顶点离v0顶点更近
    48 
    49         final[v] = TRUE;                       // 离v0顶点最近的v加入S集
    50 
    51         for (w=0; w<G.vexnum; ++w)             // 更新当前最短路径及距离
    52 
    53             if (!final[w] && (min+G.arcs[v][w].adj<D[w])) 
    54 
    55             { 
    56 
    57                 // 修改D[w]和P[w], w∈V-S
    58 
    59                 D[w] = min + G.arcs[v][w];
    60 
    61                 P[w] = P[v];P[w][w] = TRUE; //P[w] = P[v]+[w]  
    62 
    63             }
    64 
    65     }
    66 
    67 }

    二、每一对顶点之间的最短路径

    问题描述:给定带权有向图G=(V, E),对任意顶点vi,vj∈V(i≠j),求顶点vi到顶点vj的最短路径。

      解决办法1:每次以一个顶点为源点,调用Dijkstra算法n次。显然,时间复杂度为O(n3)。

      解决办法2:弗洛伊德提出的求每一对顶点之间的最短路径算法——Floyd算法,其时间复杂度也是O(n3),但形式上要简单些。

    Floyd算法

    基本思想:对于从vivj的弧,进行n次试探:首先考虑路径vi,v0,vj是否存在,如果存在,则比较vi,vjvi,v0,vj的路径长度,取较短者为从vivj的中间顶点的序号不大于0的最短路径。在路径上再增加一个顶点v1,依此类推,在经过n次比较后,最后求得的必是从顶点vi到顶点vj的最短路径。

    示例

    数据结构

    图的存储结构:带权的邻接矩阵存储结构  

    数组dist[n][n]:存放在迭代过程中求得的最短路径长度。迭代公式: 

    数组path[n][n]:存放从vi到vj的最短路径,初始为path[i][j]="vivj"。

    算法实现

     1 void ShortestPath_FLOYD(MGraph G, PathMatrix P[], DistancMatrix &D) 
     2 
     3 {
     4 
     5     // 用Floyd算法求有向网G中各对顶点v和w之间的最短路径P[v][w]及其
     6 
     7     // 带权长度D[v][w]。若P[v][w][u]为TRUE,则u是从v到w当前求得最
     8 
     9     // 短路径上的顶点。
    10 
    11     int v,w,u,i;
    12 
    13     for (v=0; v<G.vexnum; ++v)        // 各对结点之间初始已知路径及距离
    14 
    15         for (w=0; w<G.vexnum; ++w) 
    16 
    17         {
    18 
    19             D[v][w] = G.arcs[v][w].adj;
    20 
    21             for (u=0; u<G.vexnum; ++u) P[v][w][u] = FALSE;
    22 
    23             if (D[v][w] < INFINITY) 
    24 
    25             {    
    26 
    27                 // 从v到w有直接路径
    28 
    29                 P[v][w][v] = P[v][w][w] = TRUE;
    30 
    31             }
    32 
    33         }
    34 
    35     for (u=0; u<G.vexnum; ++u)
    36 
    37         for (v=0; v<G.vexnum; ++v)
    38 
    39             for (w=0; w<G.vexnum; ++w)
    40 
    41                 if (D[v][u]+D[u][w] < D[v][w]) 
    42 
    43                 {  
    44 
    45                     // 从v经u到w的一条路径更短
    46 
    47                     D[v][w] = D[v][u]+D[u][w];
    48 
    49                     for (i=0; i<G.vexnum; ++i)
    50 
    51                         P[v][w][i] =(P[v][u][i] || P[u][w][i]);
    52 
    53                 }
    54 
    55 }

    注:本文来自http://www.cnblogs.com/navorse/articles/1894297.html

     
     

    -------------------------------------------

    作者:赵杰迪

    -------------------------------------------

  • 相关阅读:
    梦断代码阅读笔记之三
    梦断代码阅读笔记二
    输入法评价
    1的个数
    团队冲刺-10
    第一阶段个人总结03
    第一阶段个人总结02
    第一阶段个人总结01
    学习进度条第十周
    学习进度条第九周
  • 原文地址:https://www.cnblogs.com/zhaojiedi1992/p/20121130_0.html
Copyright © 2011-2022 走看看