已發布·持續改進
Algorithm
圖形走訪以 BFS 或 DFS 拜訪所有可到達的頂點,是無權重最短路徑、連通元件、環偵測與拓撲排序的基礎。
圖形走訪是指在由頂點與邊組成的圖中,從起點出發沿著邊拜訪所有可到達的頂點,而且每個頂點只拜訪一次。最基本的兩種方法是廣度優先搜尋(BFS)與深度優先搜尋(DFS):BFS 使用佇列由近而遠逐層擴展,DFS 使用堆疊或遞迴沿著一條路徑走到底再回溯。圖通常以相鄰串列或相鄰矩陣儲存,迷宮這類二維網格只要把每一格視為頂點,也能用同樣的方法處理。
道路網路、社群關係、工作相依關係與網頁連結都是圖。BFS 能在所有邊成本相同的圖中求出最短路徑,DFS 則是連通元件、環偵測與拓撲排序的骨幹。建置工具安排工作順序、垃圾回收器判斷物件是否可到達、影像編輯軟體的油漆桶填色都仰賴圖形走訪,這也是技術面試與程式解題中最常見的題型之一。
建議先在紙上畫一張小圖,親手追蹤 BFS 的佇列與 DFS 的呼叫堆疊如何變化。接著自己實作這兩種演算法,特別留意何時標記已拜訪、如何記錄距離與父節點。之後再練習網格最短路徑、計算連通元件,以及用 Kahn 演算法進行拓撲排序。
相鄰串列使用 O(V + E) 記憶體,適合稀疏圖;相鄰矩陣能在 O(1) 內檢查邊是否存在,但需要 O(V^2) 記憶體。
以佇列先拜訪距離較近的頂點,因此在無權重圖中第一次得到的距離就是最短距離。
以遞迴或堆疊一路深入再回溯,是連通元件、環偵測與回溯法的基礎。
在有向無環圖中,以 Kahn 演算法或 DFS 完成順序的反序,求出滿足所有相依關係的順序。
程式以字典形式的相鄰串列建立一張有 6 個頂點的無向圖,接著用以 deque 實作的 BFS 印出從 A 到各頂點的最少邊數,並用遞迴 DFS 印出拜訪順序。兩個函式都會記錄已拜訪的頂點,不會重複處理同一個頂點。
graph_traversal.py
from collections import deque
graph = {
"A": ["B", "C"],
"B": ["A", "D"],
"C": ["A", "D", "E"],
"D": ["B", "C", "F"],
"E": ["C", "F"],
"F": ["D", "E"],
}
def bfs(start):
"""Shortest number of edges from start to every reachable vertex."""
dist = {start: 0}
queue = deque([start])
while queue:
node = queue.popleft()
for nxt in graph[node]:
if nxt not in dist:
dist[nxt] = dist[node] + 1
queue.append(nxt)
return dist
def dfs(start):
"""Vertices in depth-first visiting order."""
order, seen = [], set()
def visit(node):
seen.add(node)
order.append(node)
for nxt in graph[node]:
if nxt not in seen:
visit(nxt)
visit(start)
return order
print(bfs("A")) # {'A': 0, 'B': 1, 'C': 1, 'D': 2, 'E': 2, 'F': 3}
print(dfs("A")) # ['A', 'B', 'D', 'C', 'E', 'F']
python graph_traversal.py共六章,帶你從安裝一步步認識 圖形走訪 的核心概念。
在這裡提問、分享經驗,交流關於 圖形走訪 的看法。
還沒有討論。來發起第一則吧。
0 則留言
登入 · 登入後即可留言。
來留下第一則留言吧。