【算法】算法圖解筆記_廣度優先搜索

你常常須要解決最短路徑問題(shorterst-path problem)。解決最短路徑問題的算法被稱爲廣度優先搜索。廣度優先搜索算法最先由Edward F. Moore 1959年在「如何從迷宮中尋找出路」這一問題中提出。node

廣度優先搜索讓你可以找出兩樣東西之間的最短距離。使用廣度優先搜索能夠:python

  1. 編寫國際跳棋AI,計算最少走多少步就可獲勝;
  2. 編寫拼寫檢查器,計算最少編輯多少個地方就可將錯拼的單詞改爲正確的單詞,如將READED改成READER須要編輯一個地方;
  3. 根據你的人際關係網絡找到關係最近的醫生。

要解決最短路徑問題,須要兩個步驟。算法

  1. 使用圖來創建問題模型。
  2. 使用廣度優先搜索解決問題。

圖是什麼

圖用於模擬不一樣的東西是如何相連的。圖由節點(node)和(edge)組成。一個節點可能與衆多節點直接相連,這些節點被稱爲鄰居。樹是一種特殊的圖,其中沒有日後指的邊。網絡

在圖中,邊用來表示節點之間的關係,若關係是有方向的,則圖爲有向圖(directed graph),此時圖中的邊有箭頭。若關係沒有方向,則圖爲無向圖(undirected graph),此時圖中的邊沒有箭頭,直接相連的節點互爲鄰居。
圖片描述
如上圖是有向圖,Rama是Alex的鄰居。數據結構

廣度優先搜索

廣度優先搜索是一種用於圖的查找算法,可幫助回答兩類問題。app

  • 第一類問題:從節點A出發,有前往節點B的路徑嗎?
  • 第二類問題:從節點A出發,前往節點B的哪條路徑最短?

兩類問題並無本質區別,在實現層面僅僅第二類須要攜帶路徑的信息,由於最終一般須要返回這個路徑。spa

示例:假設你經營着一個芒果農場,須要尋找芒果銷售商,以便將芒果賣給他。在Facebook,你與芒果銷售商有聯繫嗎?爲此,你可在朋友中查找。code

算法原理
(1)建立一個朋友名單。
(2)依次檢查名單中的每一個人,看看他是不是芒果銷售商。
(3)假設你沒有朋友是芒果銷售商,那麼你就必須在朋友的朋友中查找。檢查名單中的每一個人時,你都將其朋友加入名單。blog

若找到,則表示你與芒果銷售商有聯繫;因爲在廣度優先搜索的執行過程當中,搜索範圍從起點開始逐漸向外延伸,即先檢查一度關係,再檢查二度關係,咱們找到的芒果銷售商也是關係最近的。隊列

執行過程當中,一度關係在二度關係以前加入查找名單,因此咱們優先檢查一度關係,而後纔到二度,依次進行。這須要存儲名單的數據結構有「先進先出」的特性,這種數據結構就是隊列(queue)。

隊列

相似於棧,隊列也是一種操做受限的數據結構,你不能隨機地訪問隊列中的元素。隊列只支持兩種操做:入隊出隊
圖片描述

隊列是一種先進先出(First In First Out,FIFO)的數據結構,而棧是一種後進先出(Last In First Out,LIFO)的數據結構。圖片描述

實現圖

使用散列表存儲每一個節點與鄰近節點關係。
圖片描述

graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["claire"] = ["thom", "jonny"]
graph["anuj"] = []
graph["peggy"] = []
graph["thom"] = []
graph["jonny"] = []

實現算法

算法的工做原理:
圖片描述
一點須要注意:檢查一我的以前,要確認以前沒檢查過他,這很重要,由於有可能會致使無限循環。

完整算法以下:

from collections import deque

graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["claire"] = ["thom", "jonny"]
graph["anuj"] = []
graph["peggy"] = []
graph["thom"] = []
graph["jonny"] = []


def person_is_seller(name):
    return name[-1] == 'm'

def search(name):
    search_queue = deque()
    search_queue += graph[name]
    searched = []
    while search_queue:
        person = search_queue.popleft()
        if not person in searched:
            if person_is_seller(person):
                print(person + " is a mango seller!")
                return True
            else:
                search_queue += graph[person]
                searched.append(person)
    return False

search("you")

算法的時間複雜度:O(V + E),其中V爲頂點(vertice)數,E爲邊數。

請繼續關注個人公衆號文章
圖片描述

相關文章
相關標籤/搜索