06-广度优先搜索:图、队列
數據結構和算法
基于《算法圖解》—Aditya Bhargava 和《數據結構》—嚴蔚敏
第6章廣度優先搜索
6.1 簡介
廣度優先搜索—breadth-first search,BFS.
主要內容圖和隊列。
廣度優先搜索能讓你能夠找出兩樣東西之間的最短距離,比如:編寫國際跳棋AI(Artificial Intelligence),計算最少走多少步可以獲勝;或者根據你的人際關系網絡找到關系最近的醫生。
需要兩個步驟:
(1)使用圖來建立問題模型。
(2)使用廣度優先搜索解決問題。
6.2 什么是圖
圖由節點和邊組成。一個節點可能與眾多節點直接相連,這些節點被稱為鄰居。
6.3 廣度優先搜索
廣度優先搜索是一種用于圖的查找算法,可幫助回答兩類問題:
- 第一類問題:從節點A出發,有前往節點B的路徑嗎?
- 第二類問題:從節點A出發,前往節點B的哪條路徑最短?
假設你經營著一個芒果農場,需要尋找芒果銷售商,以便將芒果賣給他。為此,你可在朋友中查找。
首先創建一個朋友名單,然后依次檢查名單中的每個人,是否是芒果銷售商:
假設你沒有朋友是芒果銷售商,那么你就必須在朋友的朋友中查找。
檢查名單中的每個人時,你都將其朋友加入名單。
6.3.1 查找最短路徑
一度關系勝過二度關系,二度關系勝過三度關系,以此類推。
廣度優先搜索不僅查找從A到B的路徑,而且找到的是最短的路徑。
只有按添加順序查找時,才能實現這樣的目的。
隊列(queue):實現按添加順序進行檢查的數據結構。
6.3.2 隊列
隊列能夠實現按添加順序進行檢查的需求。
隊列不能隨機訪問,只能支持兩種操作:入隊和出隊。
先加入的元素將先出隊并被檢查。
隊列是一種先進先出(First In First Out)的數據結構;
棧是一種后進先出(Last In First Out)的數據結構。
6.4 實現圖
圖是由多個節點組成,需要使用代碼來實現圖。
每個結點都與鄰近結點相連,散列表可以很好的實現這種關系。
散列表將鍵映射到值,比如將你這個節點映射到所有鄰居。
表示這種映射關系的Python代碼如下,
graph = {} #前面提到Python中是用字典來實現散列表。{}表示生成空字典。 graph["you"] = ["alice", "bob", "claire"] #"you"被映射到了一個數組,因此graph["you"]是一個數組,包含了"you"的所有鄰居。 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"] = [] #散列表是無序的,因此添加鍵-值對的順序不關緊要。有向圖(directed graph):有一個節點指向相鄰節點,單向關系。上圖中Anuj,Peggy,Thom,Jonny都沒有鄰居,因為他們沒有指向其他節點。
無向圖(undirected graph):沒有箭頭,直接連接的節點互為鄰居。
下面兩圖等效:
6.5 實現算法
隊列實現原理
為什么要避免被重復搜索(檢查):
上圖中Peggy既是Alice的朋友又是Bob的朋友,因此她將被加入隊列兩次;因此,搜索隊列將包含兩個Peggy。
檢查完一個人后,應將其標記為已檢查,且不再檢查;如果不這樣做,就可能會導致無限循環。
因為搜索隊列將在包含你和包含Peggy之間反復切換,從而造成無限循環。
列表是有序的。如果任務A依賴于任務B,在列表中任務A就必須在任務B后面,這被稱為拓撲排序,使用它可根據圖創建一個有序表。
6.5.1 樹
樹是特殊的圖,其中沒有往后指的邊。
樹是圖的子集,樹都是圖,圖不一定是樹。
6.6 小結
- 隊列是先進先出。
- 棧是后進先出。
- 注意避免導致無限循環。
——持續修改完善中…
總結
以上是生活随笔為你收集整理的06-广度优先搜索:图、队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop完全分子式环境搭建—问题及解
- 下一篇: 07-狄克斯特拉算法