1. 程式人生 > 其它 >No.6.2 最短路徑之Dijkstra演算法--通過邊實現鬆弛

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.

三、用陣列模擬連結串列,本人空間思維能力實在有限,沒看懂,留作後續!