[Python] 廣度優先搜索

廣度優先搜索主要解決兩個方面的問題:

  • 存不存在路徑的問題(例如,從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 > 未完,挖坑再補

發佈了18 篇原創文章 · 獲贊 41 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章