数据结构篇:校园最短路径导航(二:弗洛伊德算法理解与应用)

求最短路径最常用的有迪杰斯特拉(Dijkstra)和弗洛伊德(Floyd)算法两种。本着简洁为王道的信条,我选择了Floyd算法。

Floyd算法

首先来看一个简单图,红色标记代表在数组的下标,橙色标记代表距离(边权值)

数据结构篇:校园最短路径导航(二:弗洛伊德算法理解与应用)_第1张图片

我们用D[6][6]这个矩阵存储两点之间最短路径,用P[6][6]这个矩阵存储路径

两个矩阵初始化如下,若两点不直接联通,则初始化为无穷大

D[6][6]
  A B C D E F
A 0 7 10 5
B 7 0 8
C 8 0 6 5
D 6 0 7
E 10 7 0 4
F 5 5 4 0
P[6][6]
  A B C D E F
A 0 1 2 3 4 5
B 0 1 2 3 4 5
C 0 1 2 3 4 5
D 0 1 2 3 4 5
E 0 1 2 3 4 5
F 0 1 2 3 4 5

核心代码

    for (int k = 0; k < G->numVertexes; ++k)
    {
        for (int v = 0; v < G->numVertexes; ++v)
        {
            for (int w = 0; w < G->numVertexes; ++w)
            {
                if (D[v][w] > D[v][k] + D[k][w])
                {
                    D[v][w] = D[v][k] + D[k][w];
                    P[v][w] = P[v][k];
                }
            }
        }
    }

其中k为中转顶点下标,级无论走哪条路径,都要经过k下标的顶点,v代表起始顶点,w代表终点。 

当取k=0时代表所有路径都经过下标为0的地点(A)

  • v取2,w取3,即从C到D,有C-A-D,可惜这个路径的和不小于C-D的路径大小,所以D数组不会有变化。
  • v取1,w取4,即从B到E,有B-A-E,发现它的值为17,小于B-E的无穷大,所以D[1][4]由无穷大改为17,因为D数组变化了,所以P数组也要跟着变化,把P[1][4]改为当前P[1][0],代表从B到E下一节点为A
  • 同理在k取0时,将这个时间复杂度为O(6^2)的循环走完,那么D和P矩阵如下
D[6][6]
  A B C D E F
A 0 7 10 5
B 7 0 8 17 12
C 8 0 6 5
D 6 0 7
E 10 17 7 0 4
F 5 12 5 4 0
P[6][6]
  A B C D E F
A 0 1 2 3 4 5
B 0 1 2 3 0 0
C 0 1 2 3 4 5
D 0 1 2 3 4 5
E 0 0 2 3 4 5
F 0 0 2 3 4 5

然后取k=1,2,3,4,5遍历完成后,D和P就是我们的目标数组了。

输出结果

这个就比较简单了,比如我输入1,4,代表我想知道从B走到E的最短路径,先输出最短路径为D[1][4]。然后就是具体的路径,我们找到P[1][4],发现它等于0,意味着从B走到E要先走B-A,然后我们看P[0][4],发现它等于4,也就是E,到达终点。

void AdjacencyList::ShowShortestResult(int originPos,int endPos) {
    int temp;
    cout << "地点" << _mapName[originPos] << "到地点" << _mapName[endPos] << "最短距离为" << ShortestPathvalue[originPos][endPos] << endl;
    temp = ShortestPathmatrix[originPos][endPos];
    cout<<"具体路径为:"<<_mapName[originPos]<<"——>";
    while (temp!=endPos){
        cout<<_mapName[temp]<<"——>";
        temp = ShortestPathmatrix[temp][endPos];
    }
    cout<<_mapName[endPos]<

 

你可能感兴趣的:(C++编程,数据结构,数据结构学习笔记)