最短路徑dijkstra算法精品代碼(超詳解)

還有:Floyd 算法最短路徑問題精品(超詳解)

一:簡介

  這個算法用於解決圖中單源最短路徑問題。所謂單源節點是指給定源節點,求圖中其它節點到此源節點的最短路徑。如下圖所示:給定源節點a,求節點b到a的最短距離。

這裏寫圖片描述
(圖來自於參考資料2)

那麼如何尋找?還是以上圖爲例:

1)初始化:設定除源節點以外的其它所有節點到源節點的距離爲INFINITE(一個很大的數),且這些節點都沒被處理過。

2)從源節點出發,更新相鄰節點(圖中爲2,3,6)到源節點的距離。然後在所有節點中選擇一個最段距離的點作爲當前節點。

3)標記當前節點爲done(表示已經被處理過),與步驟2類似,更新其相鄰節點的距離。(這些相鄰節點的距離更新也叫鬆弛,目的是讓它們與源節點的距離最小。因爲你是在當前最小距離的基礎上進行更新的,由於當前節點到源節點的距離已經是最小的了,那麼如果這些節點之前得到的距離比這個距離大的話,我們就更新它)。

4)步驟3做完以後,設置這個當前節點已被done,然後尋找下一個具有最小代價(cost)的點,作爲新的當前節點,重複步驟3.

5)如果最後檢測到目標節點時,其周圍所有的節點都已被處理,那麼目標節點與源節點的距離就是最小距離了。如果想看這個最小距離所經過的路徑,可以回溯,前提是你在步驟3裏面加入了當前節點的最優路徑前驅節點信息。

看文字描述顯得蒼白無力,你可以結合上圖,看下這個視頻:http://v.youku.com/v_show/id_XMjQyOTY1NDQw.html
(dijkstra演示),然後就清楚了。
我比較懶不想打字所以以上文字來源:
代碼原創
[http://www.cnblogs.com/wb-DarkHorse/archive/2013/03/12/2948467.html]

下面代碼是帶路徑的,其他的自己可以修改。

#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
#define MAX 100
#define INF 0x3f3f3f3f
int dist[MAX], path[MAX];
struct MGraph
{
    int edges[MAX][MAX];//鄰接矩陣,記錄的是兩點之間的距離,也就是權值 
    int n,e;//頂點數和邊數
}G;
void init() {
    memset(G.edges, INF, sizeof(G.edges));//默認爲INF
}
void insert(int u, int v, int w) {
    G.edges[u][v] = w;//
}
void printfPath(int path[], int a){
    stack<int> s;
    //這個循環以由葉子結點到根結點的順序將其入棧
    while(path[a] != -1){
        s.push(a);
        a = path[a];
    } 
    s.push(a);
    while(!s.empty()){
        cout << s.top() << " ";//打印棧頂元素,實現了頂點的逆序打印
        s.pop(); 
    }
    cout << endl;
} 
void Dijkstra(MGraph g, int v, int dist[], int path[]){ //頂點默認從0到n 
    int set[MAX], min, i, j, u;
    //對各個數組進行初始化
    for(i = 0; i < g.n; i++){
        dist[i] = g.edges[v][i];
        set[i] = 0;
        if(g.edges[v][i] < INF){
            path[i] = v;
        }else{
            path[i] = -1;
        }
    } 
    set[v] = 1; 
    path[v] = -1;
    //初始化結束,關鍵操作開始
    for(i = 0; i < g.n - 1; i++)
    {
        min = INF;//找到的點   目前最小 
        //這個循環每次從剩餘頂點中選出一個頂點,通往這個頂點的路徑在通往所有剩餘頂點的路徑中是長度最短的
        for(j = 0; j < g.n; j++){
            if(set[j] == 0 && dist[j] < min){
                u = j;
                min = dist[j];
            }
        } 
        set[u] = 1;//將選出的頂點併入最短路徑中
        //這個循環以剛併入的頂點作爲中間點,對所有通往剩餘頂點的路徑進行檢測
        for(j = 0; j < g.n; j++) {
            //這個if判斷頂點u的加入是否會出現通往頂點j的更短的路徑,如果出現,則改變原來路徑及其長度,否則什麼都不做
            if(set[j] == 0 && dist[u] + g.edges[u][j] < dist[j]){
                dist[j] = dist[u] + g.edges[u][j];//更新路徑長度 
                path[j] = u;//更新路徑頂點 
            } 
        } 
    } 
}
int main() {
    init();
    int n, m;//n個點,m條邊
    int a, x, y, w;
    cin >> m >> n;
    G.e = m;
    G.n = n;

    for(int i = 0; i < m; i++){
        cin >> x >> y >> w;
        insert(x, y, w);
    }
    Dijkstra(G, 0, dist, path);
    printfPath(path, 5);
    for(int i = 0; i < n; i++) {
        cout << dist[i] << " ";
    } 
    return 0;
}
/*測試數據
12 7 
0 1 4
0 2 6
0 3 6
1 4 7
1 2 1
2 4 6
2 5 4
3 2 2
3 5 5
4 6 6
5 4 1
5 6 8
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章