本文是對 Swift Algorithm Club 翻譯的一篇文章。
Swift Algorithm Club是 raywenderlich.com網站出品的用Swift實現算法和數據結構的開源項目,目前在GitHub上有18000+⭐️,我初略統計了一下,大概有一百左右個的算法和數據結構,基本上常見的都包含了,是iOSer學習算法和數據結構不錯的資源。
🐙andyRon/swift-algorithm-club-cn是我對Swift Algorithm Club,邊學習邊翻譯的項目。因爲能力有限,如發現錯誤或翻譯不妥,請指正,歡迎pull request。也歡迎有興趣、有時間的小夥伴一塊兒參與翻譯和學習🤓。固然也歡迎加⭐️,🤩🤩🤩🤨🤪。
本文的翻譯原文和代碼能夠查看🐙swift-algorithm-club-cn/Shortest Path(Unweighted)node
最短路徑算法(Shortest Path(Unweighted Graph))git
目標:找到圖中從一個節點到另外一個節點的最短路徑。github
假設咱們如下圖爲例:算法
咱們可能想知道從節點A
到節點F
的最短路徑是什麼。swift
若是圖是未加權的,那麼找到最短路徑很容易:咱們能夠使用廣度優先搜索算法。 對於加權圖,咱們能夠使用Dijkstra算法。數據結構
廣度優先搜索是遍歷樹或圖數據結構的方法。 它從源節點開始,在移動到下一級鄰居以前首先探索直接鄰居節點。 方便的反作用是,它會自動計算源節點與樹或圖中其餘每一個節點之間的最短路徑。學習
廣度優先搜索的結果能夠用樹表示:測試
樹的根節點是廣度優先搜索開始的節點。 爲了找到從節點A
到任何其餘節點的距離,咱們只計算樹中邊的數目。 因此咱們發現A
和F
之間的最短路徑是2.樹不只告訴你路徑有多長,並且還告訴你如何實際從A
到F
(或者任何一個其餘節點)。網站
讓咱們將廣度優先搜索付諸實踐,並計算從A
到全部其餘節點的最短路徑。 咱們從源節點A
開始,並將其添加到隊列中,距離爲0
。ui
queue.enqueue(element: A)
A.distance = 0
複製代碼
隊列如今是[A]
。 咱們將A
出列並將其兩個直接鄰居節點B
和C
入列,並設置距離1
。
queue.dequeue() // A
queue.enqueue(element: B)
B.distance = A.distance + 1 // result: 1
queue.enqueue(element: C)
C.distance = A.distance + 1 // result: 1
複製代碼
隊列如今是[B, C]
。 將B
出列,並將B
的鄰居節點D
和E
入列,距離爲2
。
queue.dequeue() // B
queue.enqueue(element: D)
D.distance = B.distance + 1 // result: 2
queue.enqueue(element: E)
E.distance = B.distance + 1 // result: 2
複製代碼
隊列如今是[C, D, E]
。 將C
出列並將C
的鄰居節點F
和G
入隊,距離爲2
。
queue.dequeue() // C
queue.enqueue(element: F)
F.distance = C.distance + 1 // result: 2
queue.enqueue(element: G)
G.distance = C.distance + 1 // result: 2
複製代碼
這麼一直持續到隊列爲空,同時咱們訪問了全部節點。 每次咱們發現一個新節點時,它會得到其父節點的distance
加1.正如您所看到的,這正是廣度優先搜索算法的做用, 除此以外,咱們如今還知道距離尋找的路徑。
這是代碼:
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
let shortestPathGraph = graph.duplicate()
var queue = Queue<Node>()
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label)
queue.enqueue(element: sourceInShortestPathsGraph)
sourceInShortestPathsGraph.distance = 0
while let current = queue.dequeue() {
for edge in current.neighbors {
let neighborNode = edge.neighbor
if !neighborNode.hasDistance {
queue.enqueue(element: neighborNode)
neighborNode.distance = current.distance! + 1
}
}
}
return shortestPathGraph
}
複製代碼
在playground中進行測試:
let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA)
print(shortestPathGraph.nodes)
複製代碼
輸出結果:
Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1),
Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2),
Node(label: g, distance: 2), Node(label: h, distance: 3)
複製代碼
**注意:**這個版本的
breadthFirstSearchShortestPath()
實際上並不生成樹,它只計算距離。 有關如何經過去除邊緣將圖轉換爲樹,請參見最小生成樹。
做者:Chris Pilcher,Matthijs Hollemans
翻譯:Andy Ron
校對:Andy Ron