Floyd 的最短路径算法 C++

Posted

技术标签:

【中文标题】Floyd 的最短路径算法 C++【英文标题】:Floyd's Shortest Path Algorithm C++ 【发布时间】:2017-04-18 17:46:09 【问题描述】:

我已经在 C++ 中为弗洛伊德算法实现了一个函数,该函数可以正常工作,除了当我生成一个路径矩阵时,它会在尝试到达目的地时给出下一个节点,它将顶点放在目的地之前而不是矩阵中源的下一个节点。距离矩阵(dist)是正确的,如果源和目标之间最多有一个节点,那么整个路径矩阵是正确的。因此,如果从顶点 i 到 j 有很长的最短路径,那么 path[i][j] 应该等于连接到 i 的 k 值,而不是连接到 j 的 k 值,我不知道为什么。功能如下图。

void floyd(const Graph<City>& g, double**& dist, int**& path)

    int n = g.size();
    for (int i = 1; i <= n; i++)
    
        for (int j = 1; j <= n; j++)
        
            path[i][j]=0;
            if (i==j)
                dist[i][j]=0;
            else if (!g.isEdge(i, j))
                dist[i][j]=INFINITY;
            else
                dist[i][j]=g.retrieveEdge(i, j);
        
    
    for (int i = 1; i <= n; i++)
    
        for (int j = 1; j <= n; j++)
        
            for (int k = 1; k <= n; k++)
            
                if ((dist[i][k]!=INFINITY) && (dist[k][j]!=INFINITY) && k!=i && k!=j && i!=j)
                
                    if ((dist[i][j]) > (dist[i][k]+dist[k][j]))
                    
                        path[i][j]=k;
                        dist[i][j]=dist[i][k]+dist[k][j];
                    
                
            
        
    

【问题讨论】:

首先使用您的调试器查看代码中哪里偏离了您的设想。其次,在 C++ 中伪造基于 1 的数组是一种危险的游戏——它可能导致一次次内存覆盖。 使用 base 1 数组只会在内存中造成一些浪费的地方,我一定要注意那里的问题,但是使用调试器我只能发现它一定是我的样子覆盖路径[i][j]。它有时会被不正确的值覆盖,无论我做什么,我都不明白为什么。 如果值被“无缘无故”覆盖,那么基于 1 的数组可能是它的原因。同样,使用从 1 开始的数组是内存覆盖或在某些情况下无意使用元素 0 的主要原因,其中元素 0 是垃圾值(但不是非法内存访问)。 不是无缘无故的。只是不正​​确。它们应该被沿路径的源中的下一个节点覆盖,而不是沿路径到目的地的紧邻目的地之前的节点。 好吧,使用调试器,看看为什么这部分代码正在做它正在做的事情。我们没有minimal reproducible example,所以我们无法编译和运行任何东西。 【参考方案1】:

所以如果从顶点 i 到 j 有很长的最短路径,那么 path[i][j] 应该等于连接到 i 的 k 值,而不是连接到 j 的 k 值,我不知道为什么。

不幸的是,两者都没有。您的实现中没有任何内容可以保证path[i][j] 应该等于紧跟在i 之后的k 值,并且您观察到path[i][j] 当前是紧接在j 之前的k 值也是不正确。 (请多尝试几个样本来验证第二点。)

您的实现唯一保证的是顶点path[i][j] == k位于某处从顶点i到顶点j的最短路径中。

因此,您可以通过以下方式递归检索路径:

get_path(i, j):
    k = path[i][j]
    get_path(i, k) + k + get_path(k, j)

澄清后,there does exist a method 可以存储path[i][j] 以便它是紧跟在i 之后的顶点。

【讨论】:

以上是关于Floyd 的最短路径算法 C++的主要内容,如果未能解决你的问题,请参考以下文章

a*算法求最短路径和floyd还有dijsktra算法求最短路径的区别?

C++ 实现带权有向图的每对顶点之间的最短路径Floyd算法(完整代码)

四大算法解决最短路径问题(Dijkstra+Bellman-ford+SPFA+Floyd)

多源最短路径--Floyd-Warshall算法

最短路径之Dijkstra算法和Floyd-Warshall算法

【数据结构】最短路径之迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法