【譯】Swift算法俱樂部-最短路徑算法

本文是對 Swift Algorithm Club 翻譯的一篇文章。
Swift Algorithm Clubraywenderlich.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

假設咱們如下圖爲例:算法

Example graph

咱們可能想知道從節點A到節點F的最短路徑是什麼。swift

若是圖是未加權的,那麼找到最短路徑很容易:咱們能夠使用廣度優先搜索算法。 對於加權圖,咱們能夠使用Dijkstra算法。數據結構

未加權圖:廣度優先搜索

廣度優先搜索是遍歷樹或圖數據結構的方法。 它從源節點開始,在移動到下一級鄰居以前首先探索直接鄰居節點。 方便的反作用是,它會自動計算源節點與樹或圖中其餘每一個節點之間的最短路徑。學習

廣度優先搜索的結果能夠用樹表示:測試

The BFS tree

樹的根節點是廣度優先搜索開始的節點。 爲了找到從節點A到任何其餘節點的距離,咱們只計算樹中邊的數目。 因此咱們發現AF之間的最短路徑是2.樹不只告訴你路徑有多長,並且還告訴你如何實際從AF(或者任何一個其餘節點)。網站

讓咱們將廣度優先搜索付諸實踐,並計算從A到全部其餘節點的最短路徑。 咱們從源節點A開始,並將其添加到隊列中,距離爲0ui

queue.enqueue(element: A)
A.distance = 0
複製代碼

隊列如今是[A]。 咱們將A出列並將其兩個直接鄰居節點BC入列,並設置距離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的鄰居節點DE入列,距離爲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的鄰居節點FG入隊,距離爲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

相關文章
相關標籤/搜索