【算法设计与分析】Floyd-Warshall算法求任意两点间最短路径

版权声明:本文为博主原创文章,转载请标明出处 https://blog.csdn.net/C2681595858/article/details/85759269


实验代码(github)

一、实验内容

  • 实现Floyd-Warshall算法求解任意两点之间的最短路径。
  • 测试用图
    在这里插入图片描述
  • 预期输出
    在这里插入图片描述

二、理论准备

  • 核心思想:它去找出两点之间每一条路径,然后选择最短的那条路径,由于它要找所有的路径所以导致复杂度很高。
  • 使用条件:不能包含任何的负圈。可以有负边。
  • 这里有一个英文版的动画演示floyd-warshall算法的网页,推荐去看看,通俗易懂。
  • 伪码
    在这里插入图片描述
  • 伪码解析:
    • 首先最外层循环控制的是中间节点,然后内层的两个循环依次访问矩阵中的每个顶点对,这样给人的感觉好像就是,这个算法找到的是不是只包含三个顶点或者两个顶点的最短路径,当然不是了。
    • 不要忘记它有一个迭代的过程,想一下,第一次迭代的时候,它找到的确实是上面说的那种最短路径,因为它逐个的去尝试,并记录下了最短的那个路径值。然后当它第二次开始迭代的时候, d i k k 1 d_{ik}^{k-1} 中记住的是上次找到的那个最短路径啊,也就是说找到的是最多经过一个中间节点的最短路径,然后这次在找i到j之间经过k的最短路径的时候,首先看i到k之间的距离,而此时 d i k d_{ik} 是上次求得的最短路径,所以这次是在上次的基础上再求最短路径。这样一来到最后,i到j之间的最短路径,最多有K个顶点(包含i和j,k是图中的顶点数)。

三、实验环境

  • 操作系统及版本:windows10
  • 编译软件及版本:g++6.3.0
  • 使用的计算机语言:c++语言

四、实验过程

  • 由于这次需要使用邻接矩阵来存储,所以之前的代码就不能复用了。
  • 但是算法很简单实现起来也很方便,不过要注意的是初始化权值矩阵的时候,对角线上的元素,也就是某个顶点自己到自己的距离是0,而到其它顶点的距离是无穷大。然后真正实现的时候也没有必要用N个D矩阵,因为每次计算都要用到上一次的计算结果,所以只需要保存上一次的计算结果,而更早的结果就可以被覆盖掉。
  • 核心代码如下:
for(int k = 0; k < size; k++)
  {
    for(int i = 0; i <size; i++)
    {
      for(int j=0; j < size; j++)
      {
        int temp = D0[i][k] + D0[k][j];
        if(D0[i][k] == INT_MAX || D0[k][j] == INT_MAX)//防止溢出
          temp = INT_MAX;
        D[i][j]  = min(D0[i][j], temp);
      }
    }
    for(int i = 0; i <size; i++)
    {
      for(int j=0; j < size; j++)
        D0[i][j] = D[i][j];
    }
  }

五、实验结果

  • 最后输出的最距离矩阵
    在这里插入图片描述

六、实验总结

  • 实现比较简单,最主要问题出在了数据类型发生溢出。在初始化的时候非对角线元素初始化为INT_MAX,结果在计算的时候发生了溢出,导致输出都是复数,bug比较容易发现,所以基本理解算法思想以后,实现相对比较简单。

猜你喜欢

转载自blog.csdn.net/C2681595858/article/details/85759269