你常常須要解決最短路徑問題(shorterst-path problem)。解決最短路徑問題的算法被稱爲廣度優先搜索。廣度優先搜索算法最先由Edward F. Moore 1959年在「如何從迷宮中尋找出路」這一問題中提出。node
廣度優先搜索讓你可以找出兩樣東西之間的最短距離。使用廣度優先搜索能夠:python
要解決最短路徑問題,須要兩個步驟。算法
圖用於模擬不一樣的東西是如何相連的。圖由節點(node)和邊(edge)組成。一個節點可能與衆多節點直接相連,這些節點被稱爲鄰居。樹是一種特殊的圖,其中沒有日後指的邊。網絡
在圖中,邊用來表示節點之間的關係,若關係是有方向的,則圖爲有向圖(directed graph),此時圖中的邊有箭頭。若關係沒有方向,則圖爲無向圖(undirected graph),此時圖中的邊沒有箭頭,直接相連的節點互爲鄰居。
如上圖是有向圖,Rama是Alex的鄰居。數據結構
廣度優先搜索是一種用於圖的查找算法,可幫助回答兩類問題。app
兩類問題並無本質區別,在實現層面僅僅第二類須要攜帶路徑的信息,由於最終一般須要返回這個路徑。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爲邊數。
請繼續關注個人公衆號文章