資料結構學習筆記-佛洛依德演算法

zeta186012發表於2024-06-07

最短路徑問題的經典解法-佛洛依德演算法

問題描述:設計演算法求解圖的最短路徑

【演算法設計思想】

  1. 初始化距離矩陣:首先,將解決方案矩陣 dist[][] 初始化為輸入圖矩陣 graph[][],這個矩陣儲存了頂點之間的直接距離或者權值。
  2. 中間頂點迭代:然後,對每一個頂點作為中間頂點進行迭代。演算法透過逐步考慮中間頂點,嘗試找到更短的路徑。
  3. 源點和目標點迭代:對於每一對源點和目標點,演算法嘗試透過當前的中間頂點來縮短路徑。
  4. 更新最短路徑:如果頂點 k 在頂點 i 和 j 之間的最短路徑上,那麼更新 dist[i][j],使其成為新的最短路徑。
  5. 迭代完成:當所有的中間頂點都被考慮完畢時,演算法結束,此時 dist[][] 中儲存的就是所有頂點對之間的最短路徑。
  6. 列印最短路徑矩陣:最後,列印出計算得到的最短路徑矩陣,即圖中所有頂點對之間的最短路徑長度。

【演算法描述】

// 實現Floyd Warshall演算法
void floydWarshall(int graph[][V]) {
    // dist[][]將是輸出陣列,即最終的最短距離矩陣
    int dist[V][V], i, j, k;

    // 初始化解決方案矩陣,與輸入圖矩陣一樣
    for (i = 0; i < V; i++)
        for (j = 0; j < V; j++)
            dist[i][j] = graph[i][j];

    // 新增所有頂點一個個作為中間頂點
    for (k = 0; k < V; k++) {
        // 選擇所有頂點作為源點
        for (i = 0; i < V; i++) {
            // 選擇所有頂點作為目標點,對於每個源點和目標點對
            for (j = 0; j < V; j++) {
                // 如果頂點k在i和j之間的最短路徑上,則更新dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j])
                    dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }

    // 列印最短距離矩陣
    printSolution(dist);
}

【完整的測試程式】

#include <stdio.h>

// 定義無窮大,表示兩點間無直接連線
#define INF 99999

// 頂點數
#define V 4

// 列印解決方案的函式
void printSolution(int dist[][V]);

// 實現Floyd Warshall演算法
void floydWarshall(int graph[][V]) {
    // dist[][]將是輸出陣列,即最終的最短距離矩陣
    int dist[V][V], i, j, k;

    // 初始化解決方案矩陣,與輸入圖矩陣一樣
    for (i = 0; i < V; i++)
        for (j = 0; j < V; j++)
            dist[i][j] = graph[i][j];

    // 新增所有頂點一個個作為中間頂點
    for (k = 0; k < V; k++) {
        // 選擇所有頂點作為源點
        for (i = 0; i < V; i++) {
            // 選擇所有頂點作為目標點,對於每個源點和目標點對
            for (j = 0; j < V; j++) {
                // 如果頂點k在i和j之間的最短路徑上,則更新dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j])
                    dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }

    // 列印最短距離矩陣
    printSolution(dist);
}

void printSolution(int dist[][V]) {
    printf("以下矩陣顯示所有點對之間的最短距離\n");
    for (int i = 0; i < V; i++) {
        for (int j = 0; j < V; j++) {
            if (dist[i][j] == INF)
                printf("%7s", "INF");
            else
                printf("%7d", dist[i][j]);
        }
        printf("\n");
    }
}

int main() {
    /* 例子中的圖的權重矩陣 */
    int graph[V][V] = {{0, 5, INF, 10},
                       {INF, 0, 3, INF},
                       {INF, INF, 0, 1},
                       {INF, INF, INF, 0}
                      };

    // 執行Floyd-Warshall演算法
    floydWarshall(graph);
    return 0;
}

相關文章