Dijkstra(迪杰斯特拉)算法简介
生活随笔
收集整理的這篇文章主要介紹了
Dijkstra(迪杰斯特拉)算法简介
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
- 適用情形
- 思想
- 核心代碼
- 設計實現更多功能
- 舉例說明
適用情形
適用于權值為非負的圖的單源最短路徑
思想
在已知起點與終點的情況下。須有三個一維數組S,U,dis,S用于記錄已經查找過的點,U則記錄未查找到的點,dis用于記錄從起點到各個點間的距離。開始時,S中僅有起點,U中則是其它所有點,dis[起點]初始化為0,dis中其它元素則為起點到各點的距離,如果沒有路徑則可以記錄為INF(無窮大)或者-1。然后尋找與起點最近的點,將它加入數組S中,再更新dis的最短路徑。然后再找與起點最近的點,將它加入數組S中,再更新dis的最短路徑。知道全部更新完成。
核心代碼
//假設已知起點為u,點間的距離已存到二維數組map中,點間沒有路徑則存INF
int INF = 1e7;
int map[100][100];
int dis[100];
int u = 0;
int N = 100; //N表示城市的數量
int flag[100]; //以數組flag記錄點是否在數組S中void Dijkstra()
{//第一步:初始化兩個數組for(int i = 0; i < N; i++){dis[i] = map[u][i];flag[i] = 0;}flag[u] = 1;dis[u] = 0;//以循環來表示重復接下來的步驟,確保找到每個點for(int i = 0; i < N; i++){//第二步:找到距離起點的最近點int temp = INF, t = u;for(int j = 0; j < N; j++){if(!flag[j] && dis[j] < INF){t = j;temp = dis[j];}}if(t == u)return; //全部點已被找完則退出elseflag[t] = 1; //將找到的點加入S//第三步:更新dis數組for(int j = 0; j < N; j++){if(flag[j] == 0 && map[t][j]<INF && dis[j]>(dis[t]+map[t][j])){dis[j]=dis[t]+map[t][j];}}}
}
我將DIjkstra算法分為了三個步驟,即:
第一步:初始化兩個數組
第二步:找到距離起點的最近點
第三步:更新dis數組
其中第二和第三步需用循環滿足所有的點都被搜一遍。
設計實現更多功能
1.記錄路徑
加入一個記錄中轉點的數組即可
2.計算最短路徑的條數
加入一個記錄到每個點的路徑的數量的數組即可
3.出現路徑長度相同的情況,根據每個點的權選擇特定路徑
加入一個記錄到該點的權量的數組即可
…
總的來說,需要實現什么功能就加上一個記錄數據變化的數組即可。具體會在下面舉例說明
舉例說明
題目
分析:在這道題目中我們發現,不僅需要尋找最短路徑的長度,還需要找到最短路徑的條數,已經救援隊數量最多的那條最短路徑,故我們需加入上一部分說的三個數組。具體代碼如下:
#include<iostream>
#define K 501using namespace std;int INF = 1e7;int N, M , S , D;
int teamnumber[K]; //記錄每個城市的救援隊數量
int map[K][K]; //記錄城市間的路徑距離
int father[K]; //記錄中轉點
int dis[K]; //記錄起點到個點間的距離
int flag[K]; //記錄每個點是否已經搜索
int number[K]; //記錄起點到各點時路徑的數量
int ts[K]; //記錄救援隊的數量void Dijkstra()
{//各數組的初始化fill(dis, dis+N, INF);fill(flag,flag+N, 0);fill(number, number+N, 0);fill(ts, ts+N, 0);for(int i = 0; i < N; i++){dis[i] = map[S][i];father[i] = i;}//我們保持flag[i] == 0,在第一次搜索中會首先檢索到它,你也可以思考一下讓它為0有什么好處dis[S] = 0; number[S] = 1;ts[S] = teamnumber[S];//開始搜索每個點for(int i = 0; i < N; i++){int Min = INF, t = -1;for(int j = 0; j < N; j++){if(flag[j] == 0 && dis[j] < Min){Min = dis[j];t = j;}}if(t == -1)return;elseflag[t] = 1; for(int j = 0; j < N; j++) //注意兩條路距離相同但權值不同的情況,故分兩種情況討論{if(flag[j] == 0 && (dis[t] + map[t][j]) < dis[j] && map[t][j] < INF){dis[j] = dis[t] + map[t][j];father[j] = t;ts[j] = ts[t] + teamnumber[j];number[j] = number[t];}else if(flag[j] == 0 && (dis[t] + map[t][j]) == dis[j] && map[t][j] < INF){if((ts[t] + teamnumber [j]) > ts[j]){ts[j] = ts[t] + teamnumber[j];father[j] = t;}number[j] += number[t];}}}
}//打印路徑函數
void PP(int s, int d)
{while(father[d] != d){PP(s,father[d]);cout << father[d] << " ";return;}return;
}int main()
{cin >> N >> M >> S >> D;for(int i = 0; i < N; i++)cin >> teamnumber[i];for(int i = 0; i < N; i++){for(int j = 0; j < N; j++){map[i][j] = INF;}}int n, m ,d;for(int i = 0; i < M; i++){cin >> n >> m >> d;map[n][m] = d;map[m][n] = d;}Dijkstra();cout << number[D] << " " << ts[D] << endl;PP(S,D);cout << D;return 0;
}
需要注意的地方在代碼上都有注釋,如有問題可以在評論區提問。
總結
以上是生活随笔為你收集整理的Dijkstra(迪杰斯特拉)算法简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 弗洛伊德算法(Floyd)简介
- 下一篇: 找出最接近的相似串(DP思想)