最短路徑——dijkstra算法代碼(c語言)

最短路徑問題

  看了王道的視頻,感受雲裏霧裏的,因此寫這個博客來加深理解。(但願能在12點之前寫完)算法

1、整體思想

dijkstra算法的主要思想就是基於貪心,找出從v開始的頂點到各個點的最短路徑,作法入下數組

1.初始化三個輔助數組spa

  s[],dist[],path[]code

    s[]:這個數組用來標記結點的訪問與否,若是該結點被訪問,則爲1,若是該結點尚未訪問,則爲0;視頻

    dist[]:這個數組用來記錄當前從v到各個頂點的最短路徑,算法的核心思想就是經過不斷修改這個表實現;blog

    path[]:這個數組用來存放最短路徑;博客

2.遍歷圖,修改上面的各項數組,每次只找最短路徑,直到遍歷結束class

 

2、代碼實現

 

 1 void dijkstra(Graph G, int v)
 2 {
 3     int s[G.vexnum];
 4     int dist[G.vexnum];
 5     int path[G.vexnum];  
 6     for(int i = 0; i < G.vexnum; i++)
 7     {
 8         s[i] = 0;
 9         dist[i] = G.edge[v][i];
10         if(G.edge[v][i] == max || G.edge[v][i] == 0)
11         {
12             path[i] = -1;
13         }
14         else
15         {
16             path[i] = v;
17         }
18         s[v] = 1;
19     }
20     
21     for(int i = 0; i < G.vexnum; i++)
22     {
23         int min  = max;
24         int u;
25         for(int j = 0; j < G.vexnum; j++)
26         {
27             if(s[j] != 1 && dist[j] < min)
28             {
29                 min = dist[j];
30                 u = j;
31             }
32         }
33         s[u] = 1;
34         for(int j = 0; j < G.vexnum; j++)
35         {
36             if(s[j] != 1 && dist[j] > dist[u] + G.edge[u][j])
37             {
38                 dist[j] = dist[u] + G.edge[u][j];
39                 path[j] = u;
40             }
41         }
42     }
43 }

 

 

 

 

3、代碼解釋

先本身定義一個無窮大的值max遍歷

#define max inf

dijkstra算法傳入的兩個參爲di

圖Graph G;

起點結點 int v;

 

首先咱們須要三個輔助數組

1 int s[G.vexnum];//記錄結點時是否被訪問過,訪問過爲1, 沒有訪問過爲0
2     int dist[G.vexnum];//記錄當前的從v結點開始到各個結點的最短路徑 
3     int path[G.vexnum];//記錄最短路徑,存放的是該結點的上一個爲最短路徑的前驅結點  

初始化三個數組

 1 for(int i = 0; i < G.vexnum; i++)
 2     {
 3         s[i] = 0;//目前每一個結點均未被訪問過,設爲0 
 4         dist[i] = G.edge[v][i];//dist[]數組記錄每一個從v結點開到其餘i結點邊的長度(權值) 
 5         if(G.edge[v][i] == max || G.edge[v][i] == 0)
 6         {
 7             path[i] = -1;
 8         }//若是v到i不存在路徑或者i就是v結點時,將path[i]設爲-1,意爲目前i結點不存在路徑到v 
 9         else
10         {
11             path[i] = v;
12         }//反之,若v到i存在路徑,則v就是i的前驅結點,將path[i] = v
13         s[v] = 1;//從遍歷起點v開始,即已經訪問過頂點s[v]=1 
14     }

開始遍歷數組而且每次修改輔助數組以記錄目前的狀況,直至遍歷結束

 1 for(int i = 0; i < G.vexnum; i++)
 2     {
 3         int min  = max;//聲明一個min = max用來每次記錄此次遍歷找到的最短路徑的長度(權值) 
 4         int u;//聲明u來記錄此次歷找到的最短路徑的結點 
 5         for(int j = 0; j < G.vexnum; j++)//開始遍歷 找目前的最短路徑 
 6         {
 7             if(s[j] != 1 && dist[j] < min)
 8             {
 9                 min = dist[j];
10                 u = j;
11             }//找出v到結點j的最短路徑,而且記錄下最短路徑的結點u = j 
12         }
13         s[u] = 1;//找到結點u,即已訪問過u,s[u] = 1 
14         for(int j = 0; j < G.vexnum; j++)//開始遍歷 修改輔助數組的值 
15         {
16             if(s[j] != 1 && dist[j] > dist[u] + G.edge[u][j])
17             {
18                 dist[j] = dist[u] + G.edge[u][j]; 
19                 path[j] = u;
20             }//若是v→j的路徑比v →u→j長,那麼修改dist[j]的值爲 dist[u] + G.edge[u][j],而且修改j的前驅結點爲path[j] = u 
21         }
22     }

遍歷結束後,數組dist[]就是存放了起點v開始到各個頂點的最短路徑

最短路徑包含的結點就在path數組中

例如咱們獲得以下的path[]數組

1 path[0] = -1;//0到本身無前驅結點
2 path[1] = 0;//1的前驅爲結點0,0無前驅結點,即最短路徑爲0 →1
3 path[2] = 1;//2的前驅結爲點1,1的前驅結點0,0無前驅結點,即最短路徑爲0 →1 →2
4 path[3] = 0;//3的前驅爲結點0,0無前驅結點,即最短路徑爲0 →3
5 path[4] = 2;//4的前驅結爲點2,2的前驅結爲點1,1的前驅結點0,0無前驅結點,即最短路徑爲0 →1 →2 →4
相關文章
相關標籤/搜索