算法导论(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
复制代码
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
复制代码
frointer={}
i=5
复制代码
至此结束code
BFS所作的策略是先找到每一层的节点,再去找它的邻接表,耗时能够从两部分来看,1个是必须遍历全部节点,为V,另外每一层遍历的边的数量为 v
V
,即每一个顶点的边的个数,对于有向图来说是E,无向图就是2E,这样总的时间就是
(V+E)