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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

07-狄克斯特拉算法

發(fā)布時間:2023/12/4 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 07-狄克斯特拉算法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

數(shù)據(jù)結(jié)構(gòu)和算法
基于《算法圖解》—Aditya Bhargava 和《數(shù)據(jù)結(jié)構(gòu)》—嚴(yán)蔚敏

第7章 狄克斯特拉算法

上一章的廣度優(yōu)先搜索,找出的是段數(shù)最少的路徑;
本章狄克斯特拉算法,找出的是最快的路徑。

7.1 使用狄克斯特拉算法
步驟:
第一步:找出最便宜的節(jié)點

從起點出發(fā),前往節(jié)點A需要6分鐘,而前往節(jié)點B需要2分鐘。置于前往其他節(jié)點,先假設(shè)為不窮大。

第二步:計算經(jīng)節(jié)點B前往其各個鄰居所需的時間。

經(jīng)節(jié)點B可以找到前往節(jié)點A更短的路徑,只需要5分鐘。

對于節(jié)點B的鄰居,如果找到前往它的更短路徑,就更新其開銷:

  • 前往節(jié)點A的更短路徑(從6分鐘縮短到5分鐘)。
  • 前往終點的更短路徑(從無窮大縮短到7分鐘)。

第三步:重復(fù)

重復(fù)第一步:找出可能在最短時間內(nèi)前往的節(jié)點。 已經(jīng)對節(jié)點B執(zhí)行了第二步,除節(jié)點B外,可在最短時間內(nèi)前往的節(jié)點是節(jié)點A。

重復(fù)第二步:更新節(jié)點A的所有鄰居節(jié)點開銷。

可以發(fā)現(xiàn)前往終點的時間為6分鐘。

7.1.1
使用廣度優(yōu)先搜索來查找兩點之間的最短路徑,指的是段數(shù)最少;
而在狄克斯特拉算法中,每段都分配了一個數(shù)字或權(quán)重,因此找出的是總權(quán)重最小的路徑。

狄克斯特拉算法的4個步驟:

  • (1)找出最便宜的節(jié)點,即可在最短時間內(nèi)前往的節(jié)點。
  • (2)對于該節(jié)點的鄰居,檢查是否有前往它們的更短路徑,如果有,就更新其開銷。
  • (3)重復(fù)這個過程,直到對圖中的每個節(jié)點都這樣做了。
  • (4)計算最終路徑。

7.2 術(shù)語

  • 狄克斯特拉算法用于每條邊都有關(guān)聯(lián)數(shù)字的圖,這些數(shù)字稱為權(quán)重(weight)。
  • 帶權(quán)重的圖為加權(quán)圖(weighted graph),不帶權(quán)重的圖為非加權(quán)圖(unweight graph)。
  • 環(huán):從一個節(jié)點出發(fā),走一圈后又回到這個節(jié)點。繞環(huán)的路徑不可能是最短路徑。
  • 無向圖意味著兩個節(jié)點彼此指向?qū)Ψ?#xff0c;其實就是環(huán)。在無向圖中,每條邊都是一個環(huán)。
  • 狄克斯特拉算法只適用于有向無環(huán)圖(directed acyclic graph,DAG)。

7.3 換鋼琴例子
Rama想用自己的樂譜來換架鋼琴,那么需要確定哪種路徑將樂譜換成鋼琴時需要支付的額外費用最少。

使用狄克斯特拉算法可得到:

7.4 負(fù)權(quán)邊
如果有負(fù)權(quán)邊,就不能使用狄克斯特拉算法。
因為狄克斯特拉算法是這樣假設(shè)的:對于處理過的海報節(jié)點,沒有前往該節(jié)點的更短路徑。這種假設(shè)僅在沒有負(fù)權(quán)邊時才成立。
在包含負(fù)權(quán)邊的圖中,要找出最短路徑,可使用貝爾曼-福德算法。

7.5 實現(xiàn)
以下圖為例。

要編寫解決這個問題的代碼,需要三個散列表。

算法實現(xiàn)思路

#實現(xiàn)圖GRAPH:將節(jié)點的鄰居和前往鄰居的開銷存儲到散列表中。 graph["start"] = {} graph["start"]["a"] = 6 graph["start"]["b"] = 2graph["a"] = {} graph["a"]["fin"] = 1 #fin指到終點graph["b"] = {} graph["b"]["a"] = 3 graph["b"]["fin"] = 5graph["fin"] = {} #終點沒有任何鄰居#實現(xiàn)圖COSTS:節(jié)點的開銷指的是從節(jié)點出發(fā)前往該節(jié)點需要多長時間。 infinity = float("inf") costs = {} costs["a"] = 6 costs["b"] = 2 costs["fin"] = infinity#實現(xiàn)圖PARENTS:存儲父節(jié)點的散列表。 parents = {} parents["a"] = "start" parents["b"] = "start" parents["fin"] = None processed = [] #記錄處理過的幾點的數(shù)組,避免多次處理。

準(zhǔn)備工作做好了,接下來實現(xiàn)算法。
圖4.2

#首先定義函數(shù)find_lowest_cost_node找出開銷最低的結(jié)點 def find_lowest_cost_node(costs):lowest_cost = float("inf")lowest_cost_node = Nonefor node in costs: #遍歷所有節(jié)點cost = costs[node]if cost < lowest_cost and node not in processed: #如多當(dāng)前節(jié)點的開銷更低且未處理過,lowest_cost = cost #就將其視為開銷最低的節(jié)點lowest_cost_node nodereturn lowest_cost_node#實現(xiàn)狄克斯特拉算法 node = find_lowest_cost_node(costs) #在未處理的節(jié)點中找出開銷最小的節(jié)點。 while node is not None: #這個while循環(huán)在所有節(jié)點都被處理過后結(jié)束cost = cost[node]neighbors = graph[node]for n in neighbors.key(s): #遍歷當(dāng)前節(jié)點的所有鄰居new_cost = cost + neighbors[n]if costs[n] > new_cost: #如果經(jīng)當(dāng)前節(jié)點前往該鄰居更近costs[n] = new_cost #就更新該鄰居的開銷parents[n] = node #同時將該鄰居的父節(jié)點設(shè)置為當(dāng)前節(jié)點processed.append(node) #將當(dāng)前節(jié)點標(biāo)記為處理過node = find_lowest_cost_node(costs) #找出接下來要處理的節(jié)點,并循環(huán)

7.6 小結(jié)

  • 廣度優(yōu)先搜索用于在非加權(quán)圖中查找最短路徑。
  • 狄克斯特拉算法用于在加權(quán)圖中查找最短路徑。
  • 僅當(dāng)權(quán)重為正時狄克斯特拉算法才管用。
  • 如果圖中包含負(fù)權(quán)邊,請使用貝爾曼-福德算法。

——持續(xù)修改完善中…

總結(jié)

以上是生活随笔為你收集整理的07-狄克斯特拉算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。