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

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

Floyd算法的基本思想

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

求路径原理及正确性

Floyd算法求图最短路径及实现_第3张图片
图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 从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;
}

你可能感兴趣的:(最短路径,算法证明)