程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Dijkstra算法模版代碼C++

Dijkstra算法模版代碼C++

編輯:C++入門知識

Dijkstra(迪傑斯特拉)算法是典型的單源最短路徑算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴展,直到擴展到終點為止。Dijkstra算法是很有代表性的最短路徑算法,在很多專業課程中都作為基本內容有詳細的介紹,如數據結構,圖論,運籌學等等。Dijkstra一般的表述通常有兩種方式,一種用永久和臨時標號方式,一種是用OPEN, CLOSE表的方式,這裡均采用永久和臨時標號的方式。注意該算法要求圖中不存在負權邊。

 

 

[cpp]
/****************
 * about:Dijkstra
 * aothor:Salvador Huang
 * *******************************/ 
#include <iostream>  
#include <cstdio>  
#include <cstdlib>  
using namespace std; 
const int maxnum=100; 
const int maxint=999999; 
//個數組下標都從1開始  
int dist[maxnum];//表示當前點到源點的最短路徑長度  
int prev[maxnum];//記錄當前點的前一個結點  
int c[maxnum][maxnum];//記錄圖的兩點間路徑長度  
int n,line;//圖的節點數和路徑數  
/*
 * n--n nodes
 * v--the source node
 * dist[]--the distance from the ith node to the source node
 * prev[]--the previous node of the ith node
 * c[][]--every two nodes' distance
 */ 
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum]) 

    bool s[maxnum]; // 判斷是否已存入該點到S集合中  
    for(int i=1; i<=n; ++i) 
    { 
        dist[i] = c[v][i]; 
        s[i] = 0; // 初始都未用過該點  
        if(dist[i] == maxint) 
            prev[i] = 0; 
        else 
        prev[i] = v; 
    } 
    dist[v] = 0; 
    s[v] = 1; 
    // 依次將未放入S集合的結點中,取dist[]最小值的結點,放入結合S中  
    // 一旦S包含了所有V中頂點,dist就記錄了從源點到所有其他頂點之間的最短路徑長度  
    // 注意是從第二個節點開始,第一個為源點  
    for(int i=2; i<=n; ++i) 
    { 
        int tmp = maxint; 
        int u = v; 
        // 找出當前未使用的點j的dist[j]最小值  
        for(int j=1; j<=n; ++j) 
            if((!s[j]) && dist[j]<tmp) 
            { 
                u = j; // u保存當前鄰接點中距離最小的點的號碼  
                tmp = dist[j]; 
            } 
        s[u] = 1; // 表示u點已存入S集合中  
        // 更新dist  
        for(int j=1; j<=n; ++j) 
        if((!s[j]) && c[u][j]<maxint) 
        { 
            int newdist = dist[u] + c[u][j]; 
            if(newdist < dist[j]) 
            { 
                dist[j] = newdist; 
                prev[j] = u; 
            } 
        } 
    } 

//查找從源點v到終點u的路徑,並輸出  
void searchPath(int *prev,int v, int u) 

    int que[maxnum]; 
    int tot = 1; 
    que[tot] = u; 
    tot++; 
    int tmp = prev[u]; 
    while(tmp != v) 
    { 
        que[tot] = tmp; 
        tot++; 
        tmp = prev[tmp]; 
    } 
    que[tot] = v; 
    for(int i=tot; i>=1; --i) 
    { 
        if(i != 1) 
            cout << que[i] << " -> "; 
        else 
            cout << que[i] << endl; 
    } 

int main() 

    //freopen("input.txt", "r", stdin);  
    // 各數組都從下標1開始  
    // 輸入結點數  
    cin >> n; 
    // 輸入路徑數  
    cin >> line; 
    int p, q, len; // 輸入p, q兩點及其路徑長度  
    // 初始化c[][]為maxint  
    for(int i=1; i<=n; ++i) 
        for(int j=1; j<=n; ++j) 
            c[i][j] = maxint; 
    for(int i=1; i<=line; ++i) 
    { 
        cin >> p >> q >> len; 
        if(len < c[p][q]) // 有重邊  
        { 
            c[p][q] = len; // p指向q  
            c[q][p] = len; // q指向p,這樣表示無向圖  
        } 
    } 
    for(int i=1; i<=n; ++i) 
    dist[i] = maxint; 
    for(int i=1; i<=n; ++i) 
    { 
        for(int j=1; j<=n; ++j) 
            printf("%8d", c[i][j]); 
        printf("\n"); 
    } 
    Dijkstra(n, 1, dist, prev, c); 
    //最短路徑長度  
    cout << "源點到最後一個頂點的最短路徑長度: " << dist[n] << endl; 
    //路徑  
    cout << "源點到最後一個頂點的路徑為: "; 
    searchPath(prev, 1, n); 

/****************
 * about:Dijkstra
 * aothor:Salvador Huang
 * *******************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int maxnum=100;
const int maxint=999999;
//個數組下標都從1開始
int dist[maxnum];//表示當前點到源點的最短路徑長度
int prev[maxnum];//記錄當前點的前一個結點
int c[maxnum][maxnum];//記錄圖的兩點間路徑長度
int n,line;//圖的節點數和路徑數
/*
 * n--n nodes
 * v--the source node
 * dist[]--the distance from the ith node to the source node
 * prev[]--the previous node of the ith node
 * c[][]--every two nodes' distance
 */
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
{
    bool s[maxnum]; // 判斷是否已存入該點到S集合中
    for(int i=1; i<=n; ++i)
    {
        dist[i] = c[v][i];
        s[i] = 0; // 初始都未用過該點
        if(dist[i] == maxint)
            prev[i] = 0;
        else
        prev[i] = v;
    }
    dist[v] = 0;
    s[v] = 1;
    // 依次將未放入S集合的結點中,取dist[]最小值的結點,放入結合S中
    // 一旦S包含了所有V中頂點,dist就記錄了從源點到所有其他頂點之間的最短路徑長度
    // 注意是從第二個節點開始,第一個為源點
    for(int i=2; i<=n; ++i)
    {
        int tmp = maxint;
        int u = v;
        // 找出當前未使用的點j的dist[j]最小值
        for(int j=1; j<=n; ++j)
            if((!s[j]) && dist[j]<tmp)
            {
                u = j; // u保存當前鄰接點中距離最小的點的號碼
                tmp = dist[j];
            }
        s[u] = 1; // 表示u點已存入S集合中
        // 更新dist
        for(int j=1; j<=n; ++j)
        if((!s[j]) && c[u][j]<maxint)
        {
            int newdist = dist[u] + c[u][j];
            if(newdist < dist[j])
            {
                dist[j] = newdist;
                prev[j] = u;
            }
        }
    }
}
//查找從源點v到終點u的路徑,並輸出
void searchPath(int *prev,int v, int u)
{
    int que[maxnum];
    int tot = 1;
    que[tot] = u;
    tot++;
    int tmp = prev[u];
    while(tmp != v)
    {
        que[tot] = tmp;
        tot++;
        tmp = prev[tmp];
    }
    que[tot] = v;
    for(int i=tot; i>=1; --i)
    {
        if(i != 1)
            cout << que[i] << " -> ";
        else
            cout << que[i] << endl;
    }
}
int main()
{
    //freopen("input.txt", "r", stdin);
    // 各數組都從下標1開始
    // 輸入結點數
    cin >> n;
    // 輸入路徑數
    cin >> line;
    int p, q, len; // 輸入p, q兩點及其路徑長度
    // 初始化c[][]為maxint
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
            c[i][j] = maxint;
    for(int i=1; i<=line; ++i)
    {
        cin >> p >> q >> len;
        if(len < c[p][q]) // 有重邊
        {
            c[p][q] = len; // p指向q
            c[q][p] = len; // q指向p,這樣表示無向圖
        }
    }
    for(int i=1; i<=n; ++i)
    dist[i] = maxint;
    for(int i=1; i<=n; ++i)
    {
        for(int j=1; j<=n; ++j)
            printf("%8d", c[i][j]);
        printf("\n");
    }
    Dijkstra(n, 1, dist, prev, c);
    //最短路徑長度
    cout << "源點到最後一個頂點的最短路徑長度: " << dist[n] << endl;
    //路徑
    cout << "源點到最後一個頂點的路徑為: ";
    searchPath(prev, 1, n);
}
運行樣例:

 

\


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved