BFS 是廣度優先搜索(Breadth-First Search)的縮寫。BFS 用在尋找從起點node到目標node的最短路徑。
相比於DFS是深度優先,BFS是找完第一層找第二層、第三層…,直到寶最後一層,找到目標節點或者所有節點都被遍歷完成。在 BFS 中,節點的訪問順序是按照node到起點node的距離來決定的,距離越短的node先被訪問。
執行順序是 8 → 7 → 9 → 5 → 11 → 4 → 6 → 10 → 12
BFS 一定要有一個queue來實現,list或 set之類也沒差,主要是要有一個容器去裝node,用queue的原因是在乎順序。首先將起點節點加入queue,然後重複以下步驟直到queue為空:
- 從queue中取出一個node
- 如果該節點是目標node,則返回該node;否則將該node的所有未訪問過的鄰接node加入queue中
- 標記該node為已訪問
Normal BFS
root =nodeA
queue= collections.deque() # 做一個queue
queue.append(root) # 加入初始值
while queue: # 開頭一定有個while
node = queue.popleft() # 每一次都從queue取一個值
if node is None:
continue
# vist
print(node.val)
queue.append(node.left) # 把下一層資料加入queue
queue.append(node.right) # 把下一層資料加入queue
BFS 每個node只會被訪問一次,所以時間複雜度為 O(V+E), V 是node數,E 是邊數。BFS 的空間複雜度為 O(V),因為需要用一個queue來存儲待訪問的node。
Normal BFS 和Level Order Traversal
Normal BFS 和 Level Order Traversal 的實現方式有些不同。
剛剛以上介紹的是Normal BFS 的實現方式。
Level Order Traversal 是一種特殊的 Normal BFS,通常用於遍歷binary tree。在 Level Order Traversal 中,會從樹的root node開始訪問,首先訪問距離root node最近的node(也就是第 0 層),然後訪問距離root node為 1 的node(也就是第 1 層),以此類推,直到訪問到最深的node。
先將root node加入佇列中,然後重複以下步驟直到佇列為空:
- 從queue中取出一個node
- 將目標node的子node加入queue中
- 訪問目標node
Level Order Traversal
root =nodeA
queue = collections.deque() # 做一個queue
queue.append(root) # 加入初始值
while queue: # 開頭一定有個while
next_layer = collections.deque() # 準備下一層的queue
for node is queue: # 下一層
if node is None:
continue
# vist
next_layer.append(node.left) # 把下一層資料加入下一層的queue
next_layer.append(node.right) # 把下一層資料加入下一層的queue
queue = next_layer # 跑下一層
Level Order Traversal 可以保證每一層的node都被訪問一次,且node的訪問順序是按照層來決定的。在實現上,Level Order Traversal 可以使用一個額外的變數來紀錄當前訪問的node層是第幾層,以便區分不同層次的node。