算法導論(MIT 6.006 第13講)算法
搜索能夠理解爲探索,給定一個圖上的點S和A,須要找到從S到A的一個路徑數組
一個圖用 G=(V,E)
表示,V是頂點的集合,E是邊的集合。以下所示有兩種圖bash
網絡爬蟲、社交網絡、網絡包傳播、垃圾回收算法等網絡
使用鄰接表。它是一個數組(Adj表示)大小是 |V|,每一個元素是指向一個鏈表的指針,遍歷的方法以下app
for each vertex u in V
Adj[u] stores u's neighbors 複製代碼
好比,上所述的有向圖來講 Adj[a]={b},Adj[b]={a,c}
,對無向圖來說 Adj[a]={(a,c),(a,b)}
spa
這種表現形式所須要的空間大小爲 (V+E),|V|個頂點和|E|條邊.net
目標:對於一個給定的節點S V,經過它來遍歷它所能到達的全部節點
時間要求:O(V+E)
思路:查看給定節點,經過0步移動,可以到達的節點,這個節點就是s自己,而後從s移動一步,也就是s的鄰接表,找到他能到達的節點,依次類推,須要避免重複3d
BFS(s,Adj):
level={s:0} //第0步能到達的節點
parent={s:None}
i=1 //第0步就是s,已經到達,從第一步開始
frontier=[s] //前一層已經通過的節點 level=i-1
while frontier: //在已經通過的節點找它的相鄰節點
next=[] //當前層找到的節點
for u in frontier:
for v in Adj[u]:
if v not in level: //當前節點沒有在其它層出現過,從而避免重複
level[v]=i
parent[v]=u
next.append(v)
frontier=next
i+=1 //走下一層
複製代碼
以無向圖爲例指針
level={s:0,a:1,x:1}
parent={s:None,a:s,x:s}
frontier={a,s}
i=2
複製代碼
3. 以新的frontier爲基礎,再往前一步,發現a有z和s,可是s已經經歷過了,再也不添加,依次類推x。執行完以後
level={s:0,a:1,x:1,z:2,x:2}
parent={s:None,a:s,x:s,z:a,d:x,c:x}
frontier={z,d,c}
i=3
複製代碼
level={s:0,a:1,x:1,z:2,x:2,f:3,v:3}
parent={s:None,a:s,x:s,z:a,d:x,c:x,f:d,v:c} frontier優先存的是d
frontier={f,v}
i=4
複製代碼
5. 以新的frontier爲基礎,再往前一步,發現f,v的鄰接節點都已經計算過,再也不計入,所以最後
frointer={}
i=5
複製代碼
至此結束code
BFS所作的策略是先找到每一層的節點,再去找它的鄰接表,耗時能夠從兩部分來看,1個是必須遍歷全部節點,爲V,另外每一層遍歷的邊的數量爲 vV,即每一個頂點的邊的個數,對於有向圖來說是E,無向圖就是2E,這樣總的時間就是 (V+E)