Djikstra最短路徑演算法

SWEENEY_HE發表於2018-08-02

      一、概括:貪心策略

Dijktra最短路徑演算法採用的是一種貪心的策略,通過逐次地找到各點距起點的最短路徑並由該路徑更新該頂點出度的路徑,進而使圖中所有點距離起點路徑最短的演算法。

   詳細推導過程可見:https://blog.csdn.net/qq_35644234/article/details/60870719

      二、資料結構:

1.一維陣列:

int dist[] :用於儲存距離起點最短路徑,若與起點不連通則用一個較大的數表示(如16進位制的:0x3f3f3f)

int/bool flag[]:用於儲存已經得出最短路徑的頂點的集合,已得出則為1/true,否則為0/false

 char s[] :用於儲存圖中的頂點名稱等,也可以用一個結構體儲存。

2.二維陣列:

int map[][]:鄰接矩陣(二維陣列)的形式儲存一個圖的基本資訊,其中權重為初始路徑。

三、程式碼實現:

輸入:

總頂點數:n     總邊數:m

接下來m 行: 頂點:a 頂點:b 距離:len

輸入起點:start

輸出:

各頂點據起點的最短距離

dist [ i ]

c/c++混搭語言程式碼:

註釋:輸入資料均以1為起點,秉承勤儉節約的中華傳統,陣列都是以0為起點(其實就是懶得改了)

測試資料:

圖片來源:https://blog.csdn.net/qq_35644234/article/details/60870719

6 8
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
5 4 20
5 6 60
1

輸出:

1 ->1 : 4144959
1 ->2 : 4144959  //為一個大數,可在輸出時改成其他符號如~
1 ->3 : 10
1 ->4 : 50
1 ->5 : 30
1 ->6 : 60

#include<stdio.h>
#include<string.h>
#define MAX 100
#define inf 0x3f3f3f
#define min(a,b) a<b?a:b

int map[MAX][MAX];
bool flag[MAX];
int dist[MAX];
int n,m;//n是頂點數,m為邊數

void find_shortest(int start);

int main()
{
    int a,b,len;//頂點 頂點 距離
    int start;//起點

    memset(map,0,sizeof(int)*MAX*MAX);
    scanf("%d%d",&n,&m);
    while(m--)//獲取圖資訊
    {
        scanf("%d %d %d",&a,&b,&len);
        map[a-1][b-1] = len;//陣列以0開始,為方便輸入資料以1開始
    }
    for(int i = 0 ; i<n ; i++)
        for(int j = 0 ; j<n ; j++)
            if(map[i][j]==0)
                map[i][j] = inf;

    scanf("%d",&start);//輸入起點
    find_shortest(start-1);//方便輸入資料,start-1
    for(int i = 0 ; i<n ; i++)
      printf("%d ->%d : %d\n",start,i+1,dist[i]);//方便觀察資料i+1.

    return 0;
}

void find_shortest(int start)
{

for(int i = 0 ; i<n ; i++)
    {
        flag[i] = false;
        dist[i] = inf;
    }
    flag[0] = true;
    dist[0] = 0;//初始化集合和最短路徑

    for(int i = 0 ; i<n ; i++)
        dist[i] = map[start][i];//將起點各出度賦給最短路徑陣列

      for(int i = 0 ; i<n ; i++)//保證所有與起點連通的頂點都加入集合
      {
          int min = inf;//儲存起點到頂點的距離
          int t = start;//儲存頂點

           for(int j = 0 ; j<n ; j++)//打擂臺找集合外距起點最短距離
           {
               if(!flag[j]&&dist[j]<min)
               {
                   min = dist[j];//記錄最短距離
                   t = j;//記錄頂點
               }
           }

           if(t == start)
            return ;//沒有與起點連通的頂點

            flag[t] = true;//將該頂點加入集合
          for(int j = 0 ; j<n ; j++)//維護該頂點出度的最短路徑
          {
              if(!flag[j]&&map[t][j]<min)//保證不在集合內且與該頂點連通(出度)
                dist[j] = min(dist[j],dist[t]+map[t][j]);
          }
      }
}

 

相關文章