Floyd算法求图最短路径及实现

来源:互联网 发布:大数据分析师工资待遇 编辑:程序博客网 时间:2024/05/19 16:04

最短路径搜索是基于Floyd算法的改进。

Floyd算法的基本思想

这里写图片描述
图1 选i到j的最短路径
Floyd算法的基本思想是:比较直接从i到j和从i经k到j的路径长度,选择较短的一条。当此条最短路径选定后,无论是i->j,或者是i->k->j都可以抽象成i->j,既都是以i为起点,j为终点的一条最短路径。
此时,考虑i,j,k,之外的另一节点n,要找i到n的最短路径。
这里写图片描述
图2
重复上述比较,我们显然可以找到一条i到n的最短路径。
继续添加节点,我们显然可以任意找到一张连通图中,任意两点的最短路径。

求路径原理及正确性

这里写图片描述
图3 从终点往回找最短路径直到终点
考虑如图3的一条最短路径。要想描述这条最短路径,我们只需要知道,每一个node的前驱节点是什么,从终点一直往回追寻,直到找到起点,输出路径。
于是,我们可以用一个二维矩阵roadMap来记录前驱节点。roadMap[i][j]是从起点i到终点j的最短路径中j的前驱节点。roadMap[i][j] == k 则说明,此条路径中j的前驱节点为k,从而转化为找i到k的最短路径,而roadMap[i][k]又是i到k最短路径中k的前驱节点。依次类推,一直往回找,知道roadMap[i][i]==i,便回溯到了起点i.
问题就转化为了求这样的roadMap矩阵。
因为Floyd算法是可以求出一张连通图的任意两个节点的最短路径长度,我们在每次比较时都记录,显然也可以求出任意两个节点最短路径的前驱节点。例如,如果是i->j更短,则j前驱节点为i。若i->k->j,更短,则j前驱节点为k.

    for (int k = 1; k <=  Matrixwidth; k++) {        for (int i = 1; i <= Matrixwidth; i++) {            for (int j = 1; j <= Matrixwidth; j++) {                if (map[i][k] + map[k][j] < map[i][j]) {                    map[i][j] = map[i][k] + map[k][j];                    // record forword node                    resultRoadMap[i][j] = k;                }            }        }    }

每条路径的终点结点之前驱节点都可以求出,从而任两个路径的最短路径可以求出。
从而我们的算法正确性可以保证。

实现

下面的代码是从我的数据结构project作业中摘下来的,不能直接运行,但思想是对的。

//作用:产生roadMap矩阵//参数@ map: 地图、邻接矩阵,下标从1开始//   @ resultRoadMap: 用于存储产生的roadMap矩阵//   @ matrixwidth, 邻接矩阵多宽//返回值:无void campusMap::createRoadWay(int map[][12], int resultRoadMap[][12], int Matrixwidth) {    // initialize     for (int i  = 1; i <= Matrixwidth; i++) {        for (int j = 1; j <= Matrixwidth; j++) {            resultRoadMap[i][j] = i;        }    }    for (int k = 1; k <=  Matrixwidth; k++) {        for (int i = 1; i <= Matrixwidth; i++) {            for (int j = 1; j <= Matrixwidth; j++) {                if (map[i][k] + map[k][j] < map[i][j]) {                    map[i][j] = map[i][k] + map[k][j];                    // record forword node                    resultRoadMap[i][j] = k;                }            }        }    }}
// 作用:从roadMap中寻找某两点的最短路径// 参数: @roadMap: 上面提到的roadMap矩阵//       @start: 最短路径的起点//       @end:最短路径的终点// 返回值: vector<int> 从start到end最短路径vector<int> campusMap::findWay(int roadMap[][12], int start, int end) {    vector<int> result;    // find path backward, get a reversed road    result.push_back(end);    while(start != roadMap[start][end]) {        end = roadMap[start][end];        result.push_back(end);    }    result.push_back(start);    // reverse the reversed path, get the correct path    int tmp, halfSize, size;    halfSize = result.size()/2;    size = result.size();    for (int i  = 0; i < halfSize; i++) {        tmp = result[i];        result[i] = result[size - 1 - i];        result[size - 1 -i] = tmp;     }    // return the correct path    return result;}
0 0