贪心算法——Dijkstra最短路径
14天閱讀挑戰(zhàn)賽
目錄
1.問(wèn)題描述
2.問(wèn)題分析
3.算法設(shè)計(jì)
4.C++程序
5.算法分析
1.問(wèn)題描述
? ? ? ? 對(duì)于有向帶權(quán)圖G=(V,E),其中每條邊的權(quán)值都是非負(fù)實(shí)數(shù)。給定V中的一個(gè)節(jié)點(diǎn)(稱(chēng)為源點(diǎn)),計(jì)算源點(diǎn)到其他各節(jié)點(diǎn)之間的最短路徑,即單源最短路徑。
2.問(wèn)題分析
????????Dijkstra算法是解決單源最短路徑問(wèn)題的貪心算法。Dijkstra算法基本思路是先求出源點(diǎn)離當(dāng)前節(jié)點(diǎn)最短的一條路徑,然后根據(jù)當(dāng)前最短路徑末端點(diǎn)能夠到達(dá)的點(diǎn)求出下一條離源點(diǎn)最近的路徑,直到求出源點(diǎn)到其他各節(jié)點(diǎn)的最短路徑。
3.算法設(shè)計(jì)
????????將節(jié)點(diǎn)集合V劃分為兩部分——集合S和V-S(節(jié)點(diǎn)總的集合減去已經(jīng)確定最短路徑的點(diǎn)的集合)。其中,集合S中的節(jié)點(diǎn)到源點(diǎn)的最短路徑已經(jīng)確定,集合S中的節(jié)點(diǎn)到源點(diǎn)的最短路徑已經(jīng)確定,集合V-S中節(jié)點(diǎn)的路徑稱(chēng)為特殊路徑,數(shù)組dist[]用于記錄從源點(diǎn)到每個(gè)節(jié)點(diǎn)的最短特殊路徑的長(zhǎng)度。Dijkstra算法的貪心策略是選擇最短的特殊路徑長(zhǎng)度dist[t],將節(jié)點(diǎn)t添加到集合S中,同時(shí)借助節(jié)點(diǎn)t更新dist[]。一旦集合S包含了所有的節(jié)點(diǎn),dist[]就是從源點(diǎn)到其他節(jié)點(diǎn)的最短路徑長(zhǎng)度。
具體步驟如下:
1)確定合適的數(shù)據(jù)結(jié)構(gòu)。用鄰接矩陣(二維數(shù)組G[][])存儲(chǔ)圖,用一維數(shù)組dist[i]記錄從源點(diǎn)到節(jié)點(diǎn)i的最短路徑長(zhǎng)度,用一維數(shù)組p[i]記錄最短路徑上節(jié)點(diǎn)的直接前驅(qū),例如p[2]=3,則2的前一個(gè)節(jié)點(diǎn)為3;
2)初始化。假設(shè)節(jié)點(diǎn)u為源點(diǎn),令集合S={u},對(duì)于集合V-S中的節(jié)點(diǎn)i,初始化dist[i]=G[u][i]。入股從源點(diǎn)u到節(jié)點(diǎn)有邊相連,就初始化p[i]=u,否則初始化p[i]=-1;
3)找最小。根據(jù)貪心策略查找集合V-S中dist[]最小的節(jié)點(diǎn)t,t就是集合V-S中距離源點(diǎn)u最近的節(jié)點(diǎn),將節(jié)點(diǎn)t添加到集合S中;
4)執(zhí)行松弛操作。對(duì)于集合V-S中的所有節(jié)點(diǎn)j,檢查是否可以借助節(jié)點(diǎn)t得到更短的路徑。如果源點(diǎn)u經(jīng)節(jié)點(diǎn)t到節(jié)點(diǎn)j的路徑更短(即:dist[j]>dist[t]+G[t][j]),則更新dist[j]=dist[t]+G[t][j](即執(zhí)行松弛操作)并記錄j的直接前驅(qū)為t(即p[j]=t)。
5)重復(fù)步驟3和4,直到集合V-S為空。由此可以得到源點(diǎn)u到其他各節(jié)點(diǎn)的最短路徑長(zhǎng)度,此位還可以通過(guò)前驅(qū)數(shù)組p[]逆向找到最短路徑上經(jīng)過(guò)的點(diǎn)。
4.C++程序
//program 2.5.0 dijkstra算法 #include<iostream> #include<algorithm> #include<stack> using namespace std; const int N = 1005; const int INF = 0x3f3f3f3f; //無(wú)窮大 int G[N][N], dist[N]; //G[][]為鄰接矩陣,dist[i]表示源點(diǎn)到結(jié)點(diǎn)i的最短路徑長(zhǎng)度 int p[N]; //p[i]表示源點(diǎn)到結(jié)點(diǎn)i的最短路徑上i的前驅(qū) int n, m; //n為結(jié)點(diǎn)數(shù),m為邊數(shù) bool flag[N]; //如果flag[i]等于true,說(shuō)明結(jié)點(diǎn)i已經(jīng)加入到S集合;否則i屬于V-S集合void dijkstra(int u) {for (int i = 1; i <= n; i++) { //初始化dist[i] = G[u][i]; //初始化源點(diǎn)u到其他各個(gè)結(jié)點(diǎn)的最短路徑長(zhǎng)度f(wàn)lag[i] = false;if (dist[i] == INF)p[i] = -1; //源點(diǎn)u到該結(jié)點(diǎn)的路徑長(zhǎng)度為無(wú)窮大,說(shuō)明源點(diǎn)u與結(jié)點(diǎn)i不相鄰elsep[i] = u; //說(shuō)明結(jié)點(diǎn)i與源點(diǎn)u相鄰,設(shè)置i的前驅(qū)為u}dist[u] = 0;flag[u] = true; //初始時(shí),集合S中只有源點(diǎn)ufor (int i = 1; i < n; i++) {int temp = INF, t = u;for (int j = 1; j <= n; j++) { //在集合V-S中尋找距離源點(diǎn)u最近的結(jié)點(diǎn)tif (!flag[j] && dist[j] < temp) {t = j;temp = dist[j];} }if (t == u) return; //找不到t,跳出循環(huán)flag[t] = true; //否則,將t加入S集合for (int j = 1; j <= n; j++) { //更新t的鄰接點(diǎn)j的最短路徑長(zhǎng)度,松弛操作 if (!flag[j] && dist[j] > dist[t] + G[t][j]) {dist[j] = dist[t] + G[t][j];p[j] = t;}}} }void findpath(int u){//輸出源點(diǎn)到其它各結(jié)點(diǎn)的路徑 int x;stack<int>s;cout<<"源點(diǎn)為:"<<u<<endl;for(int i=1;i<=n;i++){x=p[i];while(x!=-1){s.push(x);x=p[x];}cout<<"源點(diǎn)到其它各結(jié)點(diǎn)最短路徑為:";while(!s.empty()){cout<<s.top()<<"--";s.pop();}cout<<i<<";最短距離為:"<<dist[i]<<endl;} }int main() {int u, v, w, st;//u、v表示結(jié)點(diǎn),w表示u--v的距離,st表示源點(diǎn)int t;//測(cè)試用例數(shù) cin >> t;while (t--) {cin >> n >> m; //n為節(jié)點(diǎn)個(gè)數(shù),m為兩點(diǎn)直接有相連權(quán)值的個(gè)數(shù)for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)G[i][j] = INF;//初始化鄰接矩陣為無(wú)窮大while (m--) {cin >> u >> v >> w;G[u][v] = min(G[u][v], w); //鄰接矩陣儲(chǔ)存,保留最小的距離}cin >> st;//輸入源點(diǎn) dijkstra(st);for (int i = 1; i <= n; i++) {//輸出源點(diǎn)到各結(jié)點(diǎn)的最短路徑長(zhǎng)度,即dist[]數(shù)組 if (i != 1) cout << " ";if (dist[i] == INF)cout << "impossible";elsecout << dist[i];}cout << endl;findpath(st);}system("pause");return 0; }5.算法分析
1)算法復(fù)雜度:找最小以及松弛操作本身執(zhí)行了n次,需要重復(fù)n-1,總的執(zhí)行次數(shù)均為次,時(shí)間復(fù)雜度為O()。
2)空間復(fù)雜度:輔助數(shù)組flag[]、p[]以及變量i、j、t、temp等,空間復(fù)雜度為O(n)。
?
總結(jié)
以上是生活随笔為你收集整理的贪心算法——Dijkstra最短路径的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: F-16飞行器非线性Simulink模型
- 下一篇: ME811刷机GoogleMarket