1. 程式人生 > >資料結構之最短路徑Dijkdtra演算法

資料結構之最短路徑Dijkdtra演算法

複製程式碼
/*
 * Dijkstra最短路徑。
 * 即,統計圖(G)中"頂點vs"到其它各個頂點的最短路徑。
 *
 * 引數說明:
 *        G -- 圖
 *       vs -- 起始頂點(start vertex)。即計算"頂點vs"到其它頂點的最短路徑。
 *     prev -- 前驅頂點陣列。即,prev[i]的值是"頂點vs"到"頂點i"的最短路徑所經歷的全部頂點中,位於"頂點i"之前的那個頂點。
 *     dist -- 長度陣列。即,dist[i]是"頂點vs"到"頂點i"的最短路徑的長度。
 */
void dijkstra(Graph G, int vs, int prev[], int dist[])
{
    int i,j,k;
    int min;
    int tmp;
    int flag[MAX];      // flag[i]=1表示"頂點vs"到"頂點i"的最短路徑已成功獲取。

    // 初始化
    for (i = 0; i < G.vexnum; i++)
    {
        flag[i] = 0;              // 頂點i的最短路徑還沒獲取到。
        prev[i] = 0;              // 頂點i的前驅頂點為0。
        dist[i] = G.matrix[vs][i];// 頂點i的最短路徑為"頂點vs"到"頂點i"的權。
    }

    // 對"頂點vs"自身進行初始化
    flag[vs] = 1;
    dist[vs] = 0;

    // 遍歷G.vexnum-1次;每次找出一個頂點的最短路徑。
    for (i = 1; i < G.vexnum; i++)
    {
        // 尋找當前最小的路徑;
        // 即,在未獲取最短路徑的頂點中,找到離vs最近的頂點(k)。
        min = INF;
        for (j = 0; j < G.vexnum; j++)
        {
            if (flag[j]==0 && dist[j]<min)
            {
                min = dist[j];
                k = j;
            }
        }
        // 標記"頂點k"為已經獲取到最短路徑
        flag[k] = 1;

        // 修正當前最短路徑和前驅頂點
        // 即,當已經"頂點k的最短路徑"之後,更新"未獲取最短路徑的頂點的最短路徑和前驅頂點"。
        for (j = 0; j < G.vexnum; j++)
        {
            tmp = (G.matrix[k][j]==INF ? INF : (min + G.matrix[k][j])); // 防止溢位
            if (flag[j] == 0 && (tmp  < dist[j]) )
            {
                dist[j] = tmp;
                prev[j] = k;
            }
        }
    }

    // 列印dijkstra最短路徑的結果
    printf("dijkstra(%c): \n", G.vexs[vs]);
    for (i = 0; i < G.vexnum; i++)
        printf("  shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);
}
複製程式碼