Dijkstra-迪傑斯特拉 算法 算法是處理單源最短路徑問題常用的算法,雖然時間複雜度(n^2)較高(但是可以優化),但是編寫起來方便在處理小數據時還是很方便的.
dijkstra 算法,在使用時需要指定一個起始點 n,因爲這是 計算一個點到其它點最短路徑的算法,這裏需要 3 個數組 S , U 和flag 來輔助完成,其中 S 數組用來儲存 點 i 到 n 的 最短路徑 即 S[i] ,U 數組來儲存 還未 計算最短路徑的 點 ,flag[i] 說明 點 i 已經 被計算出到n的最短路徑 ,來看看過程是怎樣的
假如 有 4 個 點 A B C D 計算 A到其餘三點的最短路徑(如下圖)
① 開始 S中只有A本身 ,U 中爲剩餘節點 S {A(0)} U {B(3),C(5),D(max)}
A(0) 表示 A 到 其本身的距離 爲 0 ,D(max) 表示 D與A在一開始沒有直接連接
② 現在 U中尋找距離A點最近的點 (這個點到A肯定是最短的了) 我們找到了B,所以 將 B加入S中 並在U中去除(用flag標記一下就OK)
這時 數組是 S{A(0),B(3) } U{C(3),D(MAX)} 然後我們再拿剛拿出的點B能直接到達的點 :只有C 我們看到 AB + BC < AC 然後將 U 中的 C(5) 換成 C (4);
③ 重複 ① ② 操作;
簡單介紹了過程之後看一下如何用代碼實現(我代碼將S 和 U合併了):
#include<stdio.h>
#include<string.h>
#define MAXN 10000000
int maps[100][100];
int s[100];//用來存儲點到原點的距離 假設 點由數字 1-100 表示
int flag[100];//用來判斷點是否計算過
void init(){
int i,j;
memset(flag,-1,sizeof(int)*100);
for (i=0;i<100;i++)
for (j=0;j<100;j++)
{
if (i==j)
maps[i][j] = 0;
else
maps[i][j] = MAXN;
}
}
void dijkstra(int x,int n){ //X 表示 起始點 ,n表示點的數量
int i,j,k;
for (i=1;i<=n;i++)
s[i] = maps[x][i];
s[x] = 0;
flag[x] = 1;
for (i=1;i<=n;i++)
{
int min = MAXN;
for (j=1;j<=n;j++)
{
if (flag[j]==-1 && min > s[j])
{
min = s[j]; //記錄最小值
k = j; // 記錄最小值的點
}
}
flag[k] = 1;//標記最小值的點 該點距離起始點已是最短距離
for (j=1;j<=n;j++)
{
if (flag[j]!=1&&s[k]+maps[k][j] < s[j])
{
s[j] = min + maps[k][j];
}
}
}
}
int main (){
int i,n,m,a,b,c,x;//n表示點的個數 m表示邊的個數,a,b 存儲點 ,c存儲邊的權值,x爲起始點
scanf("%d%d",&n,&m);
init();
for (i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
maps[a][b] = c;
maps[b][a] = c;
}
scanf("%d",&x);
dijkstra(x,n);
for (i=1;i<=n;i++)
printf("%d\n",s[i]);
}