廣度優先搜索主要解決兩個方面的問題:
- 存不存在路徑的問題(例如,從A點是否可以達到B點)
- 無權重的最短路徑問題(例如,從A點到B點的最短路徑)
Graph Data Structure的表示
上面這種圖可以用Python表示爲:
# sample graph implemented as a dictionary
graph = {'A': ['B', 'C', 'E'],
'B': ['A','D', 'E'],
'C': ['A', 'F', 'G'],
'D': ['B'],
'E': ['A', 'B','D'],
'F': ['C'],
'G': ['C']}
FIFO隊列
BFS分層
類似通訊錄一樣,BFS搜索最短路徑時,是按層級進行檢索
先解決存不存在的問題
# -*- coding:utf-8 -*-
# TODO: 解決路徑顯示的問題
# deque函數用來創建一個雙端隊列
from collections import deque
# -----------------
# 使用字典來表示圖
# graph = {}
# key 代表當前節點標識(例如可以是反映名字的string)
# value 代表與該節點相關的下一層節點列表
# Example:
# graph = [1:[4,2],2:[3,4],3:[4],4:[5],5:[]]
def BFS_Search(graph,startNode,stopNode):
# 創建一個待處理節點的隊列
search_queue = deque()
# 將起始節點的下一層節點加入到待處理隊列中
search_queue += graph[startNode]
# 創建一個檢索過的列表,避免出現節點間的相互添加
searched = [startNode]
# 當隊列不爲空時
while search_queue:
# 從隊列中取出要處理的節點
currentNode = search_queue.popleft()
# 保證只對未處理過的節點進行判斷
# Ex: A的下一層包含B,B的下一層又包含A
if currentNode not in searched:
# 這裏寫具體的終止條件
# if 滿足終止條件後return True
if currentNode == stopNode:
searched.append(stopNode)
return True
else:
# else如果當前節點沒有滿足終止條件
# 則將當前節點的下一層節點加到隊列尾部
search_queue += graph[currentNode]
# 將檢查過的節點加入到searched列表中
searched.append(currentNode)
return False
# Example One 從你身邊的人脈網中找一個叫Tom的人
graph = {}
graph["Sprinkle"] = ["Alice","Claire","Bob"]
graph["Claire"]=["Sprinkle"]
graph["Alice"] = ["Peggy"]
graph["Bob"] = ["Sprinkle","Peggy","Tom"]
graph["Peggy"] =[]
graph["Tom"] = []
searched = BFS_Search(graph, "Sprinkle","Tom")
print(searched)
再解決最短路徑的問題
# -*- coding:utf-8 -*-
# TODO: 解決路徑顯示的問題
# deque函數用來創建一個雙端隊列
from collections import deque
# -----------------
# 使用字典來表示圖
# graph = {}
# key 代表當前節點標識(例如可以是反映名字的string)
# value 代表與該節點相關的下一層節點列表
# Example:
# graph = [1:[4,2],2:[3,4],3:[4],4:[5],5:[]]
def BFS_Search(graph,startNode,stopNode):
# 創建一個待處理節點的隊列
search_queue = deque()
# 將起始節點的下一層節點加入到待處理隊列中
search_queue += graph[startNode]
# 創建一個檢索過的列表,避免出現節點間的相互添加
searched = [startNode]
# 當隊列不爲空時
while search_queue:
# 從隊列中取出要處理的節點
currentNode = search_queue.popleft()
# 保證只對未處理過的節點進行判斷
# Ex: A的下一層包含B,B的下一層又包含A
if currentNode not in searched:
# 這裏寫具體的終止條件
# if 滿足終止條件後return True
if currentNode == stopNode:
searched.append(stopNode)
return searched
else:
# else如果當前節點沒有滿足終止條件
# 則將當前節點的下一層節點加到隊列尾部
search_queue += graph[currentNode]
# 將檢查過的節點加入到searched列表中
searched.append(currentNode)
return False
def BFS_ShortestPath(graph,startNode,stopNode):
searched = BFS_Search(graph,startNode,stopNode)
path = [stopNode]
# 當起始節點與目標節點不同時
while stopNode != startNode:
# 對檢索過的節點進行遍歷
for node in searched:
# 先找包含了目標節點的上一級節點
if stopNode in graph[node]:
# 將上一級節點加到stopNode之前
path.insert(0, stopNode)
# 將目標節點更換爲node
stopNode = node
break
return path
# Example One 從你身邊的人脈網中找一個叫Tom的人
graph = {}
graph["Sprinkle"] = ["Alice","Claire","Bob"]
graph["Claire"]=["Sprinkle"]
graph["Alice"] = ["Peggy"]
graph["Bob"] = ["Sprinkle","Peggy","Tom"]
graph["Peggy"] =[]
graph["Tom"] = []
path = BFS_ShortestPath(graph,"Sprinkle","Tom")
print(path)
舉個例子
< Python Breath First Search Maze solving program > 未完,挖坑再補