【譯】Swift算法俱樂部-最小生成樹(未加權(quán)圖)

Swift算法俱樂部

本文是對 Swift Algorithm Club 翻譯的一篇文章助被。
Swift Algorithm Clubraywenderlich.com網(wǎng)站出品的用Swift實現(xiàn)算法和數(shù)據(jù)結(jié)構(gòu)的開源項目剖张,目前在GitHub上有18000+??切诀,我初略統(tǒng)計了一下,大概有一百左右個的算法和數(shù)據(jù)結(jié)構(gòu)搔弄,基本上常見的都包含了幅虑,是iOSer學(xué)習(xí)算法和數(shù)據(jù)結(jié)構(gòu)不錯的資源。
??andyRon/swift-algorithm-club-cn是我對Swift Algorithm Club顾犹,邊學(xué)習(xí)邊翻譯的項目。由于能力有限,如發(fā)現(xiàn)錯誤或翻譯不妥,請指正极阅,歡迎pull request。也歡迎有興趣、有時間的小伙伴一起參與翻譯和學(xué)習(xí)??帖族。當(dāng)然也歡迎加??茶鹃,??????????。
本文的翻譯原文和代碼可以查看??swift-algorithm-club-cn/Minimum Spanning Tree(Unweighted)


最小生成樹(未加權(quán)圖)(Minimum Spanning Tree (Unweighted Graph))

最小生成樹描述了包含訪問圖中每個節(jié)點所需的最小數(shù)目邊的路徑。

看下圖:

如果我們從節(jié)點a開始并想要訪問每個其他節(jié)點逞怨,那么最有效的路徑是什么革砸? 我們可以使用最小生成樹算法來計算它。

這是圖的最小生成樹。 它由粗體邊表示:

繪制為更一般形式的樹扒怖,它看起來像這樣:

要計算未加權(quán)圖上的最小生成樹蚂蕴,我們可以使用廣度優(yōu)先搜索 算法鸟整。廣度優(yōu)先搜索從源節(jié)點開始,并在移動到下一級鄰居之前首先通過探索直接鄰居節(jié)點來遍歷圖涉茧。如果我們通過選擇性地刪除邊來調(diào)整此算法钳垮,那么它可以將圖轉(zhuǎn)換為最小生成樹。

讓我們逐步完成這個例子。 我們從源節(jié)點a開始,將其添加到隊列中并將其標(biāo)記為已訪問。

queue.enqueue(a)
a.visited = true

隊列現(xiàn)在是[a]。 與廣度優(yōu)先搜索一樣落追,我們將隊列前面的節(jié)點a出隊病苗,并將其直接鄰居節(jié)點bh入隊。 將它們標(biāo)記為訪問過挚赊。

queue.dequeue()   // a
queue.enqueue(b)
b.visited = true
queue.enqueue(h)
h.visited = true

隊列現(xiàn)在是[b, h]。 將b出隊并將鄰居節(jié)點c入隊箕宙。 將其標(biāo)記為已訪問柬帕。 將bh邊移除凤跑,因為已經(jīng)訪問過h

queue.dequeue()   // b
queue.enqueue(c)
c.visited = true
b.removeEdgeTo(h)

隊列現(xiàn)在是[h, c]。 將h出隊并將鄰居節(jié)點gi入隊耍群,并將它們標(biāo)記為已訪問曹抬。

queue.dequeue()   // h
queue.enqueue(g)
g.visited = true
queue.enqueue(i)
i.visited = true

隊列現(xiàn)在是[c, g, i]。 將c出隊并將鄰居節(jié)點df入隊,并將它們標(biāo)記為已訪問。 刪除ci之間的邊壳咕,因為已經(jīng)訪問了i

queue.dequeue()   // c
queue.enqueue(d)
d.visited = true
queue.enqueue(f)
f.visited = true
c.removeEdgeTo(i)

隊列現(xiàn)在是[g, i, d, f]。 出隊g地啰。 它的所有鄰居都已經(jīng)被發(fā)現(xiàn)了亏吝,所以沒有什么可以入隊的止喷。 刪除gf的邊预愤,以及gi的邊嗜傅,因為已經(jīng)發(fā)現(xiàn)了fi

queue.dequeue()   // g
g.removeEdgeTo(f)
g.removeEdgeTo(i)

隊列現(xiàn)在是[i, d, f]乒融。 出隊i掰盘。 這個節(jié)點沒有別的辦法。

queue.dequeue()   // i

隊列現(xiàn)在是[d, f]赞季。 將d出隊并將鄰居節(jié)點e入隊愧捕。 將其標(biāo)記為已訪問。 刪除df的邊申钩,因為已經(jīng)訪問了f次绘。

queue.dequeue()   // d
queue.enqueue(e)
e.visited = true
d.removeEdgeTo(f)

隊列現(xiàn)在是[f, e]。 出列f撒遣。 刪除fe之間的邊邮偎,因為已經(jīng)訪問過e

queue.dequeue()   // f
f.removeEdgeTo(e)

隊列現(xiàn)在是[e]义黎。 出隊e钢猛。

queue.dequeue()   // e

隊列為空,這意味著已計算出最小生成樹轩缤。

代碼如下:

func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph {
  let minimumSpanningTree = graph.duplicate()

  var queue = Queue<Node>()
  let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label)
  queue.enqueue(sourceInMinimumSpanningTree)
  sourceInMinimumSpanningTree.visited = true

  while let current = queue.dequeue() {
    for edge in current.neighbors {
      let neighborNode = edge.neighbor
      if !neighborNode.visited {
        neighborNode.visited = true
        queue.enqueue(neighborNode)
      } else {
        current.remove(edge)
      }
    }
  }

  return minimumSpanningTree
}

此函數(shù)返回一個新的Graph對象,該對象僅描述最小生成樹贩绕。 在圖中火的,這將是僅包含粗體邊的圖。

將此代碼放在playground上淑倾,進行測試:

let graph = Graph()

let nodeA = graph.addNode("a")
let nodeB = graph.addNode("b")
let nodeC = graph.addNode("c")
let nodeD = graph.addNode("d")
let nodeE = graph.addNode("e")
let nodeF = graph.addNode("f")
let nodeG = graph.addNode("g")
let nodeH = graph.addNode("h")
let nodeI = graph.addNode("i")

graph.addEdge(nodeA, neighbor: nodeB)
graph.addEdge(nodeA, neighbor: nodeH)
graph.addEdge(nodeB, neighbor: nodeA)
graph.addEdge(nodeB, neighbor: nodeC)
graph.addEdge(nodeB, neighbor: nodeH)
graph.addEdge(nodeC, neighbor: nodeB)
graph.addEdge(nodeC, neighbor: nodeD)
graph.addEdge(nodeC, neighbor: nodeF)
graph.addEdge(nodeC, neighbor: nodeI)
graph.addEdge(nodeD, neighbor: nodeC)
graph.addEdge(nodeD, neighbor: nodeE)
graph.addEdge(nodeD, neighbor: nodeF)
graph.addEdge(nodeE, neighbor: nodeD)
graph.addEdge(nodeE, neighbor: nodeF)
graph.addEdge(nodeF, neighbor: nodeC)
graph.addEdge(nodeF, neighbor: nodeD)
graph.addEdge(nodeF, neighbor: nodeE)
graph.addEdge(nodeF, neighbor: nodeG)
graph.addEdge(nodeG, neighbor: nodeF)
graph.addEdge(nodeG, neighbor: nodeH)
graph.addEdge(nodeG, neighbor: nodeI)
graph.addEdge(nodeH, neighbor: nodeA)
graph.addEdge(nodeH, neighbor: nodeB)
graph.addEdge(nodeH, neighbor: nodeG)
graph.addEdge(nodeH, neighbor: nodeI)
graph.addEdge(nodeI, neighbor: nodeC)
graph.addEdge(nodeI, neighbor: nodeG)
graph.addEdge(nodeI, neighbor: nodeH)

let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA)

print(minimumSpanningTree) // [node: a edges: ["b", "h"]]
                           // [node: b edges: ["c"]]
                           // [node: c edges: ["d", "f"]]
                           // [node: d edges: ["e"]]
                           // [node: h edges: ["g", "i"]]

注意: 在未加權(quán)的圖上馏鹤,任何生成樹始終是最小生成樹。 這意味著您還可以使用深度優(yōu)先搜索來查找最小生成樹娇哆。

作者:Chris Pilcher湃累, Matthijs Hollemans
翻譯:Andy Ron
校對:Andy Ron

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勃救,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子治力,更是在濱河造成了極大的恐慌蒙秒,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宵统,死亡現(xiàn)場離奇詭異晕讲,居然都是意外死亡,警方通過查閱死者的電腦和手機马澈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門瓢省,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痊班,你說我怎么就攤上這事勤婚。” “怎么了涤伐?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵馒胆,是天一觀的道長。 經(jīng)常有香客問我废亭,道長国章,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任豆村,我火速辦了婚禮液兽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掌动。我一直安慰自己四啰,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布粗恢。 她就那樣靜靜地躺著柑晒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眷射。 梳的紋絲不亂的頭發(fā)上匙赞,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機與錄音妖碉,去河邊找鬼涌庭。 笑死,一個胖子當(dāng)著我的面吹牛欧宜,可吹牛的內(nèi)容都是我干的坐榆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼冗茸,長吁一口氣:“原來是場噩夢啊……” “哼席镀!你這毒婦竟也來了匹中?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤豪诲,失蹤者是張志新(化名)和其女友劉穎顶捷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跛溉,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡焊切,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芳室。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片专肪。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖堪侯,靈堂內(nèi)的尸體忽然破棺而出嚎尤,到底是詐尸還是另有隱情,我是刑警寧澤伍宦,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布芽死,位于F島的核電站,受9級特大地震影響次洼,放射性物質(zhì)發(fā)生泄漏关贵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一卖毁、第九天 我趴在偏房一處隱蔽的房頂上張望揖曾。 院中可真熱鬧,春花似錦亥啦、人聲如沸炭剪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奴拦。三九已至,卻和暖如春届吁,著一層夾襖步出監(jiān)牢的瞬間错妖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工疚沐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暂氯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓濒旦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親再登。 傳聞我的和親對象是個殘疾皇子尔邓,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容