No.6.2 最短路徑之Dijkstra演算法--通過邊實現鬆弛
一、簡介:
Dijkstra演算法:指定一個點(源點),求其到其他點的最短路徑。稱之為“單源最短路徑”.
一維陣列 dis 記錄源點到其餘各點的初始距離:
1.先找到一個距離源點A最近的點B,(區別於上一節的假設:求兩點之間的最短距離,必須引入另外的點),因為邊最小,其他邊都是正數,即使引入其他點也不能使得這兩點間的距離變小!
2.再引用上節的理論,將B最為引入點,查詢是否可以縮短源點A到其他點的距離,更新dis;
3.再找到第二距離遠的點C,重複以上更新,直到全部節點嘗試完畢。
術語:
dis[i] 表示源點 1 到 i 的距離;
e[i][j] 表示 i 到 j 的初始距離,對應二維陣列;
dis[i] + e[i][j] 表示源點 1 通過節點 i 到達 j 的距離;
二、完整code
int main(){
int inf=9999999; //根據邊長和邊數決定這個值的設定
int i,j,k,h,n,m,min; //min,h用於中間變數,臨時儲存 dis[] 最小值和索引下標
int a,b,c;
int e[100][100],dis[10];
int book[10]={0}; //已經確定的最短路徑,不需再回首
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++) // Initialize
for(j=1;j<=n;j++)
{
if(i==j) e[i][j]=0;
else e[i][j]=inf;
}
for(i=1;i<=m;i++) // Input manually
{
scanf("%d %d %d",&a,&b,&c);
e[a][b]=c;
}
for(i=1;i<=n;i++) //從1號定點開始
dis[i]=e[1][i];
book[1]=1;
for(i=1;i<=n;i++){ //雖然 i=1 已經確定了,但是為了迴圈的好看(程式碼簡單),還是寫上吧:每個點都要嘗試
min=inf;
for(j=1;j<=n;j++){ //找到距離 i 最近的點,雖然有些點已經不需要再重複嘗試,還是為了程式碼簡單
if(book[j]==0 && dis[j]<min){
min=dis[j]; // min實現自我遞迴:1.min=dis[i],k=i; 2.if(book[j]==0 && dis[j]<dis[i]) min=dis[j],k=j;
k=j;
}
}
book[k]=1; //不管你是i,還是j,都賦值給k了,所以book[k]=1總是沒錯的
for(h=1;h<=n;h++){ //確定好參考點之後,再把 dis[] 重新走一遍
if(e[k][h]<inf && dis[h]>e[k][h]+dis[k]){ // e[k][h]<inf 這個條件,持保留意見
dis[h]=e[k][h]+dis[k];
}
}
}
for(i=1;i<=n;i++)
printf("%d\t",dis[i]);
getchar();getchar();return 0;
}
演算法的時間複雜度O(N*N + N) ~ O(N*N),結合堆和稀疏圖,還可以優化演算法時間複雜度約為O(M+N)logN.
三、用陣列模擬連結串列,本人空間思維能力實在有限,沒看懂,留作後續!