图-最短路径-Floyd

本文详细介绍Floyd算法原理及其应用,该算法能够在O(n³)的时间复杂度内计算出图中每一对顶点间的最短路径。通过逐步迭代,最终确定所有顶点间的最短路径。
每一对顶点之间的最短路径
Floyd
  • 时间复杂度:O(n3)O(n^3)O(n3)

    弗洛伊德算法仍从图的带权邻接矩阵cost出发,其基本思想是:

    假设求从顶点viv_ivivjv_jvj的最短路径:

    ​ 如果从viv_ivivjv_jvj有弧,则从viv_ivivjv_jvj存在一条长度为arcs[i][j]arcs[i][j]arcs[i][j]的路径,该路径不一定是最短路径,尚需进行n次试探。

    ​ 首先考虑路径(vi,vo,vj)(v_i,v_o,v_j)(vi,vo,vj)是否存在(即判别弧(vi,vo)(v_i,v_o)(vi,vo)(vo,vj)(v_o,v_j)(vo,vj)是否存在)

    ​ 如果存在:则比较(vi,vj)(v_i,v_j)(vi,vj)(vi,vo,vj)(v_i,v_o,v_j)(vi,vo,vj)的路径长度取长度较短者为从viv_ivivjv_jvj的中间顶点的序号不大于0的最短路
    径。

    ​ 假如在路径上再增加一个顶点v1v_1v1,也就是说,如果(vi,...,v1)(v_i,...,v_1)(vi,...,v1)(v1,...,vj)(v_1,...,v_j)(v1,...,vj)分别是当前找到的中间顶点的序号不大于0的最短路径,那么(vi,...,v1,...,vj)(v_i,...,v_1,...,v_j)(vi,...,v1,...,vj)就有可能是从viv_ivivjv_jvj的中间顶点的序号不大于1的最短路径。

    ​ 将它和已经得到的从viv_ivivjv_jvj中间顶点序号不大于0的最短路径相比较,从中选出中间顶点的序号不大于1的最短路径之后,再增加一个顶点v2v_2v2,继续进行试探。依次类推。

    ​ 在一般情况下,若(vi,...,vk)(v_i,...,v_k)(vi,...,vk)(vk,...,vj)(v_k,...,v_j)(vk,...,vj)分别是从viv_ivivkv_kvk和从vkv_kvkvjv_jvj的中间顶点的序号不大于k-1的最短路径,则将(vi,...,vk,...,vj)(v_i,...,v_k,...,v_j)(vi,...,vk,...,vj)和已经得到的从 viv_ivivjv_jvj​且中间顶点序号不大于k-1的最短路径相比较,其长度较短者便是从v:到v;的中间顶点的序号不大于k的最短路径。

    ​ 这样,在经过n次比较后,最后求得的必是从viv_ivivjv_jvj的最短路径。按此方法,可以同时求得各对顶点间的最短路径。

    现定义一个n阶方阵序列D(−1),D(0),D(1),...,D(k),...,D(n−1)D^{(-1)},D^{(0)},D^{(1)},...,D^{(k)},...,D^{(n-1)}D(1),D(0),D(1),...,D(k),...,D(n1)
    其中

    D(−1)[i][j]=G.arcs[i][j]D^{(-1)}[i][j]=G.arcs[i][j]D(1)[i][j]=G.arcs[i][j]

    D(k)[i][j]=Min{D(k−1)[i][j],D(k−1)[i][k]+D(k−1)[k][j]} 0≤K≤n−1D^{(k)}[i][j]=Min \left\{D^{(k-1)}[i][j],D^{(k-1)}[i][k]+D^{(k-1)}[k][j]\right\} \space 0≤K≤n-1D(k)[i][j]=Min{D(k1)[i][j],D(k1)[i][k]+D(k1)[k][j]} 0Kn1

    从上述计算公式可见,D(1)[i][j]D^{(1)}[i][j]D(1)[i][j]是从vi到vi的中间顶点的序号不大于1的最短路径的长度;D(k)[i][j]D^{(k)}[i][j]D(k)[i][j]是从vi到v;的中间顶点的序号不大于k的最短路径的长度;D(n−1)[i][j]D^{(n-1)}[i][j]D(n1)[i][j]就是从vi到vi的最短路径的长度。
    由此可得Floyd算法。

    void ShortestPath FLOYD(MGraph G, PathMatrix &P[], DistancMatrix &D){
      //用Floyd算法求有向网G中各对顶点v和w之间的最短路径[v][w]及其
      //带权长度D[v][w]。若P[v][w][u]为TRUE,则u是从v到w当前求得最
      //短路径上的顶点。   
      for (v=0;v<G.vexnum; ++v) // 各对节点之间初始已知路径及距离
          for (w=0; w< G.vexnum; ++w) {
              D[v][w] = G.arcs[v][w]; // 初始时边的距离
              for (u=0; u< G.vexnum; ++u) P[v][w][u] = FALSE; //默认最短路径上的顶点都置为FALSE
              if (D[v][w] < INFINITY){ // 从v 到w有直接路径
                  P[v][w][v] = True; P[v][w][w] = TRUE; //有直接路径的置为TRUE
              }//if
          }//for
      for (u = 0; u< G.vexnum; ++u)// 定义的k 序号不大于k的最短路径的长度
          for (v=0;v<G.vexnum; ++v)
              for (w = 0; w<G.vexnum;++w)
                  if (D[v][u]+D[u][w]<D[v][w]){ // 从v经u到w的一条路径更短
                      D[v][w] = D[v][u]+D[u][w];
                      for (i = 0; i < G.vexnum; ++i)
                          P[v][w][i] = P[v][u][i] || P[u][w][i];
                  }// if
    }// ShortestPath FLOYD
    

在这里插入图片描述

在这里插入图片描述

参考
  • [数据结构(C语言版)].严蔚敏
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值