日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最短路径 - 迪杰斯特拉(Dijkstra)算法

發布時間:2024/4/13 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最短路径 - 迪杰斯特拉(Dijkstra)算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

對于網圖來說,最短路徑,是指兩頂點之間經過的邊上權值之和最少的路徑,并且我們稱路徑上的第一個頂點為源點,最后一個頂點為終點。最短路徑的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法。本文先來講第一種,從某個源點到其余各頂點的最短路徑問題。

這是一個按路徑長度遞增的次序產生最短路徑的算法,它的大致思路是這樣的。

比如說要求圖7-7-3中頂點v0到v1的最短路徑,顯然就是1。由于頂點v1還與v2,v3,v4連線,所以此時我們同時求得了v0->v1->v2 = 1+3 = 4, v0->v1->v3 = 1 +7 = 8, v0->v1->v4 = 1+5 = 6。

現在我們可以知道v0到v2的最短距離為4而不是v0->v2 直接連線的5,如圖7-7-4所示。由于頂點v2還與v4,v5連線,所以同時我們求得了v0->v2->v4其實就是v0->v1->v2->v4 = 4+1=5,v0->v2->v5 = 4+7 = 11,這里v0->v2我們用的是剛才計算出來的較小的4。此時我們也發現v0->v1->v2->v4 = 5要比v0->v1->v4 = 6還要小,所以v0到v4的最短距離目前是5,如圖7-7-5所示。

當我們要求v0到v3的最短路徑時,通向v3的三條邊,除了v6沒有研究過外,v0->v1->v3 = 8, 而v0->v4->v3 = 5 +2 = 7,因此v0到v3的最短路徑為7,如圖7-7-6所示。

如上所示,這個算法并不是一下子就求出來v0到v8的最短路徑,而是一步步求出它們之間頂點的最短距離,過程中都是基于已經求出的最短路徑的基礎上,求得更遠頂點的最短路徑,最終得到想要的結果。


程序代碼如下:(改編自《大話數據結構》)

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
? #include<iostream>
using?namespace?std;

#define?MAXEDGE?20
#define?MAXVEX?20
#define?INFINITY?65535

typedef?struct
{
????int?vexs[MAXVEX];
????int?arc[MAXVEX][MAXVEX];
????int?numVertexes,?numEdges;
}?MGraph;

typedef?int?PathArc[MAXVEX];
typedef?int?ShortPathTable[MAXVEX];

/*?構建圖?*/
void?CreateMGraph(MGraph?*G)
{
????int?i,?j;

????/*?printf("請輸入邊數和頂點數:");?*/
????G->numEdges?=?16;
????G->numVertexes?=?9;

????for?(i?=?0;?i?<?G->numVertexes;?i++)/*?初始化圖?*/
????{
????????G->vexs[i]?=?i;
????}

????for?(i?=?0;?i?<?G->numVertexes;?i++)/*?初始化圖?*/
????{
????????for?(?j?=?0;?j?<?G->numVertexes;?j++)
????????{
????????????if?(i?==?j)
????????????????G->arc[i][j]?=?0;
????????????else
????????????????G->arc[i][j]?=?G->arc[j][i]?=?INFINITY;
????????}
????}

????G->arc[0][1]?=?1;
????G->arc[0][2]?=?5;
????G->arc[1][2]?=?3;
????G->arc[1][3]?=?7;
????G->arc[1][4]?=?5;

????G->arc[2][4]?=?1;
????G->arc[2][5]?=?7;
????G->arc[3][4]?=?2;
????G->arc[3][6]?=?3;
????G->arc[4][5]?=?3;

????G->arc[4][6]?=?6;
????G->arc[4][7]?=?9;
????G->arc[5][7]?=?5;
????G->arc[6][7]?=?2;
????G->arc[6][8]?=?7;

????G->arc[7][8]?=?4;


????for(i?=?0;?i?<?G->numVertexes;?i++)
????{
????????for(j?=?i;?j?<?G->numVertexes;?j++)
????????{
????????????G->arc[j][i]?=?G->arc[i][j];
????????}
????}

}
/*??Dijkstra算法,求有向網G的pos頂點到其余頂點v的最短路徑P[v]及帶權長度D[v]?*/
/*??P[v]的值為前驅頂點下標,D[v]表示pos到v的最短路徑長度和?*/
/*??pos?取值?0~MG.numVertexs-1?*/
void?ShortestPath_Dijkstra(MGraph?MG,?int?pos,?PathArc?P,?ShortPathTable?D)
{
????int?v,?w,?k,?min;
????int?final[MAXVEX];/*?final[w]=1表示求得頂點pos至w的最短路徑?*/
????for?(v?=?0;?v?<?MG.numVertexes;?v++)
????{
????????final[v]?=?0;/*?全部頂點初始化為未知最短路徑狀態?*/
????????D[v]?=?MG.arc[pos][v];/*?將與pos點有連線的頂點加上權值?*/
????????P[v]?=?0;/*?初始化路徑數組P為0??*/
????}

????D[pos]?=?0;?/*說明源點pos沒有到自身的路徑?*/
????P[pos]?=?-1;?/*?-1表示自身無前驅頂點*/
????final[pos]?=?1;/*?pos至pos不需要求路徑?*/
????/*?開始主循環,每次求得pos到某個v頂點的最短路徑?*/
????for?(v?=?1;?v?<?MG.numVertexes;?v++)
????{
????????min?=?INFINITY;/*?當前所知離pos頂點的最近距離?*/
????????for?(w?=?0;?w?<?MG.numVertexes;?w++)/*?尋找離pos最近的頂點?*/
????????{
????????????if?(!final[w]?&&?D[w]?<?min)
????????????{
????????????????k?=?w;
????????????????min?=?D[w];/*?w頂點離pos頂點更近?*/
????????????}
????????}
????????final[k]?=?1;/*?將目前找到的最近的頂點置為1?*/
????????for?(w?=?0;?w?<?MG.numVertexes;?w++)/*?修正當前最短路徑及距離?*/
????????{
????????????if?(!final[w]?&&?(min?+?MG.arc[k][w]?<?D[w]))
????????????{
????????????????/*??說明找到了更短的路徑,修改D[w]和P[w]?*/
????????????????D[w]?=?min?+?MG.arc[k][w];/*?修改當前路徑長度?*/
????????????????P[w]?=?k;
????????????}
????????}
????}
????/*?結束循環,若P[w]?=?0;說明頂點w的前驅為pos?*/
}


int?main(void)
{
????MGraph?MG;
????PathArc?P;
????ShortPathTable?D;
????int?i,?j,?pos?=?2;
????CreateMGraph(&MG);
????ShortestPath_Dijkstra(MG,?pos,?P,?D);

????cout?<<?"逆序最短路徑如下:"?<<?endl;
????for?(i?=?8;?i?>=?0;?i--)
????{
????????j?=?i;
????????while?(P[j]?!=?-1?&&?P[j]?!=?0)
????????{
????????????cout?<<?"v"?<<?j?<<?"<-"?<<?"v"?<<?P[j]?<<?"??";
????????????j?=?P[j];
????????}
????????cout?<<?"v"?<<?j?<<?"<-"?<<?"v"?<<?pos?<<?"??";
????????cout?<<?endl;

????}
????cout?<<?endl;

????return?0;
}
輸出為:


其中CreateMGraph函數創建出來的鄰接矩陣如圖7-7-7所示。


相信經過上面的分析,大家可以自己進行循環跑程序分析了,循環結束后final = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }表示所有頂點均完成了最短路徑的查找工作。此時D = { 4, 3, 0, 3, 1, 4, 6, 8, 12 }, 注意我們在前面說過Dijkstra算法可以求某個源點到其他頂點的最短路徑,現在我們上面程序中給出的pos = 2, 即源點為v2, 所以D[2] = 0 表示沒有到自身的路徑。D數組表示v2到各個頂點的最短路徑長度,比如D[8] =1+2 + 3 + 2 + 4 = 12。此時P = { 1, 0, -1, 4, 0, 4, 3, 6, 7 }, 可以這樣來理解,P[2] = -1 表示v2沒有前驅頂點,P[1] = P[4] = 0 表示v1和v4的前驅頂點為源點v2。再比如P[8] = 7,表示v8的前驅是v7;再由P[7] = 6,表示v7的前驅是v6; P[6] = 3 表示v6的前驅是v3, 這樣就可以得到v2 到 v8的最短路徑為v2->v4->v3->v6->v7->v8,從上面的程序輸出也可以驗證我們的推測。

其實最終返回的數組D和數組P,是可以得到v2到任意一個頂點的最短路徑和路徑長度的,也就是說我們通過Dijkstra算法解決了從某個源點到其余各頂點的最短路徑問題。從循環嵌套可以得到此算法的時間復雜度為O(n^2),如果我們要得到任一頂點到其余頂點的最短路徑呢?最簡單的辦法就是對每個頂點都當作源點進行一次Dijkstra算法,等于在原有算法的基礎上,再來一次循環,此時整個算法的時間復雜度就為O(n^3)。

總結

以上是生活随笔為你收集整理的最短路径 - 迪杰斯特拉(Dijkstra)算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。