大話數據結構學習筆記 - 圖的最短路徑之Floyd算法

大話數據結構學習筆記 - 圖的最短路徑之Floyd算法

本文是對網結構最短路徑的另一求法,上一節講的爲Dijkstra算法,本節將Floyd算法, 有關於最短路徑的講解也在上一節。

Floyd算法

算法簡介

弗洛伊德Floyd算法也是一種在給定的加權圖中求最短路徑的算法,求的所有頂點到所有頂點的時間複雜度爲O(n3) , 是由1978年的圖靈獲得者、斯坦福大學計算機科學系教授羅伯特·弗洛伊德命名。

基本思想

首先定義兩個二維數組D[MAXVEX][MAXVEX]P[MAXVEX][MAXVEX]D數組代表頂點到頂點的最短路徑權值和矩陣, P代表對應頂點的最小路徑前驅矩陣。 初始時,將矩陣D中頂點D[v][w]設置爲頂點v到頂點w的權值,若兩頂點不相連,則D[v][w] = INF。接下來對矩陣D更新, 如果D[v][w] > D[v][k] + D[k][w]k表示v、w兩頂點通過中轉頂點,該表達式表示通過中轉頂點的權值和較小時,更新v、w權值和。下面通過實例進行演示

算法圖解

Graph_ShortestPath_Floyd_image_1

初始狀態:初始化PD矩陣, D表示頂點到頂點的權值, P表示頂點v到頂點w的最短路徑。若頂點之間直接相連,則D矩陣值爲權值,否則爲無窮大。

第一步: 首先以第一個頂點v0爲中轉點, 即所有的頂點都經過v0中轉,計算是否有最短路徑的變化,結果沒有

第二步: 以v1頂點爲中轉點,即所有頂點都經過v1中轉, 可以看到,D[0][2] > D[0][1] + D[1][2], 即表示以v1爲中轉點,頂點v0v2的權值和變小了,即D[0][2] = 4, 同理可得D[0][3] = 8, D[0][4] = 6, 然後更新D矩陣和P矩陣

Graph_ShortestPath_Floyd_image_2

第三步: 接下來,依次以每個頂點作爲中轉點, 得到以每個頂點做爲中轉點後的權值, 得到最終的矩陣D和矩陣P

Graph_ShortestPath_Floyd_image_3

代碼

無向圖結構

#define MAXVEX 9
#define INF 65535
typedef int Patharc[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];
typedef struct
{
    int vexs[MAXVEX];
    int arc[MAXVEX][MAXVEX];
    int numVertexes, numEdges;
}MGraph;

算法

/* Floyd 算法, 求網圖 G 中各頂點 v 到其餘頂點 w 的最短路徑 P[v][w] 及帶權長度 D[v][w] */
void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D) {
    /* 初始化 D 與 P */
    for (int v = 0; v < G.numVertexes; ++v) {
        for (int w = 0; w < G.numVertexes; ++w) {
            (*D)[v][w] = G.arc[v][w];  /* D[v][w] 值即爲對應頂點間的權值 */
            (*P)[v][w] = w;  /* 初始化 P */
        }
    }
    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]) {
                    /* 如果經過下標爲 k 的頂點路徑比原兩點間路徑更短 */
                    (*D)[v][w] = (*D)[v][k] + (*D)[k][w];  /* 將當前兩點間權值設爲更小的一個 */
                    (*P)[v][w] = (*P)[v][k];  /* 路徑設置爲經過下標爲 k 的頂點 */
                }
            }
        }
    }
}

打印各頂點間的最短路徑

/* 打印各頂點間的最短路徑 */
void ShowShortestPath(MGraph G, Patharc *P, ShortPathTable *D)
{
    for(int v = 0; v < G.numVertexes; ++v)
    {
        for(int w = v + 1; w < G.numVertexes; ++w)
        {
            printf("v%d-v%d weight: %d ",v,w,(*D)[v][w]);
            int k = (*P)[v][w];  /* 獲得第一個路徑頂點下標 */
            printf(" path: %d",v);  /* 打印源點 */
            while (k != w)  /* 如果路徑頂點下標不是終點 */
            {
                printf(" -> %d",k); /* 打印路徑頂點 */
                k = (*P)[k][w];  /* 獲得下一個路徑頂點下標 */
            }
            printf(" -> %d\n",w);   /* 打印終點 */
        }
        printf("\n");
    }
}

源碼

鄰接矩陣最短路徑之Floyd算法

結語

關於圖的最短路徑的兩種方法都已整理,繼續加油go go go

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章