最短路徑問題

2021-10-01 14:45:54 字數 3391 閱讀 3638

**網

本文將解析如何使用 dijkstra 演算法求解最短路徑問題

如下圖:

就像上圖, 每乙個點可以理解成乙個岔路口, 線段就是路徑, 線段上的值為長度, 如何找到從 v0到各個岔路口的最小值, 也就是最短路徑問題

最短路徑問題 和 深度廣度搜尋一樣, 都是建立在圖這個資料結構上的, 因此我們可以選用鄰接表 或者是臨接矩陣 來表示上圖 , 封裝類如下:

public class graph01 

}// 新增點的方法

public void addedge(int s, int e, int w)

它大概長這個樣子:

一條邊有三個描述屬性, 兩邊的頂點 + 權重

// 邊的封裝類

使用兩個屬性描述頂點, 分別是 dist 和 id , 比如我們描述 v3 , 那麼它的id = 3 , dist是到起點v0的距離, 故 dist =13

// 圖中各個點的封裝類

還是看這個圖: 比如我們尋找的最短路徑就是 v0 到 其它所有的頂點的最短路徑 ,按照廣度優先順序遍歷這個圖尋找 v0 的臨接點 , 於是我們能發現 v1 v2 v4 v6 這四個點都是v0的臨界點, 然後我們分別給 v1 v2 v4 v6 這四個點做出如下的標記

v1.dist = 13   // dist表示的是 當前點到起點的距離

v2.dist = 8

v4.dist = 30

v6.dist = 32

但是我們發現, 直接相連 , 並不一定是最短的 , 就像下面這樣 , 雖然都能到v4 , 但是很顯然, 如果按照v0 -> v2 -> v3 -> v4會更近 ,這就意味著我們需要不斷的更新每乙個節點到起點的dist值

v0.dist + v4.dist = 30

v0.dist + v2.dist + v3.dist = 19

那麼, 是否存在乙個點到起點v0的dist是 百分百確定並且不會更改呢??? 沒錯,就是 它所有臨界點中, dist最小的那個點於是, 我們的編碼流程就是下面這樣找到起點

將起點新增進佇列(因為我們是廣度優先遍歷)

迴圈遍歷佇列中的值

如果當前點 == 結束點 , 就 break

從佇列中取出dist 最小的點 記作 當前點

找到當前點的所有直接 臨接點

挨個遍歷根節點的臨界點

如何未被訪問過, 並且 當前點.dist + 當前路徑的長度 < 當前點的下乙個點的dist (說明找到了比原來標記的最短路徑 , 更短的路徑) , 然後 用前者更新後者的值將當前點加入到可以還原路徑長度的輔助陣列中

如果當前點的下乙個點未被訪問過, 標記它被訪問了, 然後加入佇列中

預設所有的點的 dist = integer.maxvalue

如果看這圖, 用筆跟著上面的邏輯畫一下的話, 就能發現, 確實能找到 v0到其他各個點的最短路徑, 唯一不好理解的部分就是我們用黑色加粗的地方,

我們舉例子解釋一下 , 還是上圖:

比如, 就從開頭說 :

通過上面的步驟4 , 我們可以遍歷到v0的直接臨接點是 v4 , 這是第一次訪問, 於是我們可以繼續處理, 然後我們按照 步驟4.1 進行判斷v0.dist + 30 < v4.dist條件滿足了(預設所有的點的 dist = integer.maxvalue), 於是我們就更新v4.dist = v0.dist + 30 < v4.dist =30

經過了幾輪迴圈後, 假設當前已經是v3了, 這是我們繼續來到步驟4.1中進行判斷,v3.dist + 6 < v4.dist我們發現也是滿足的, 因為一開始算出了 v4.dist= 30 , 於是進一步更新這個值, 使v4.dist = v3.dist + 6, 這樣迭代下面 , 我們就能獲取到起點 到所有點的最短路徑

最短路徑 dijkstra 演算法實現如下:

public void dijkstra(int start, int end) 

// 獲取頂點, 並賦初值為0

vertex startvertex = vertices[0];

startvertex.dist = 0;

visited[start] = true;

// 建立佇列,並將頭結點入隊

queuequeue = new priorityqueue<>();

queue.add(startvertex);

while (!queue.isempty()) }}

}system.out.print(start);

print( start,end ,resultarray);

} /**

* 例如:

* 數值: 0 0 0 2 3 1 1

* 下標: 0 1 2 3 4 5 6

* 我們得到 從 0 - 6 的路徑該怎麼走呢? 按照如下的順序將方法壓入棧, 彈棧時即可獲取到路徑

* * | 0 0 |

* | 0 1 |

* | 0 6 | 方法棧

* ----------

*/private void print(int start, int end, int resultarray)

最短路 最短路徑問題

題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。input 共有n m 3行,其中 第一行為乙個整數n。第2行...

Codeup最短路徑 最短路徑問題

給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。輸入n,m,點的編號是1 n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t 起點s,...

最短路徑之最短路徑問題

提交 狀態 討論版 命題人 外部匯入 題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點間的直線距離。現在的 任務是找出從一點到另一點之間的最短路徑。輸入共n m 3行,...