comparison Graph.py @ 8:1defe6fcf9d3

Improvements to Graph's bfs.
author Brian Neal <bgneal@gmail.com>
date Mon, 03 Dec 2012 19:11:17 -0600
parents 69e5977417b3
children 84e183b40c63
comparison
equal deleted inserted replaced
7:69e5977417b3 8:1defe6fcf9d3
5 5
6 Copyright 2011 Allen B. Downey. 6 Copyright 2011 Allen B. Downey.
7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html. 7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html.
8 """ 8 """
9 import itertools 9 import itertools
10 from collections import deque
10 11
11 12
12 class GraphError(Exception): 13 class GraphError(Exception):
13 """Exception for Graph errors""" 14 """Exception for Graph errors"""
14 pass 15 pass
195 def bfs(self, start, visit_func=None): 196 def bfs(self, start, visit_func=None):
196 """Perform a breadth first search starting at node start. 197 """Perform a breadth first search starting at node start.
197 198
198 The function visit_func, if supplied, is invoked on each node. 199 The function visit_func, if supplied, is invoked on each node.
199 200
200 """ 201 The set of visited nodes is returned.
201 # Mark all vertices as unvisited 202
202 vs = self.vertices() 203 """
203 for v in vs: 204 visited = set()
204 v.visited = False
205 205
206 # Create a work queue consisting initially of the starting node 206 # Create a work queue consisting initially of the starting node
207 queue = [start] 207 queue = deque([start])
208 208
209 while queue: 209 while queue:
210 # retrieve first item from the queue 210 # retrieve first item from the queue
211 v = queue.pop(0) 211 v = queue.popleft()
212 212
213 if v.visited: 213 if v in visited:
214 continue # Skip this one if we've seen it before 214 continue # Skip this one if we've seen it before
215 215
216 # Mark it as visited and invoke user's function on it 216 # Mark it as visited and invoke user's function on it
217 v.visited = True 217 visited.add(v)
218 if visit_func: 218 if visit_func:
219 visit_func(v) 219 visit_func(v)
220 220
221 # Add the adjacent neigbors to the node to the queue 221 # Add the adjacent neigbors to the node to the queue
222 queue.extend(self.out_vertices(v)) 222 queue.extend(self.out_vertices(v))
223
224 return visited
223 225
224 def is_connected(self): 226 def is_connected(self):
225 """Returns True if the graph is connected (there is a path from every 227 """Returns True if the graph is connected (there is a path from every
226 node to every other node) and False otherwise. 228 node to every other node) and False otherwise.
227 229
228 """ 230 """
229 vs = self.vertices() 231 vs = self.vertices()
230 if len(vs): 232 if len(vs):
231 self.bfs(vs[0]) 233 visited = self.bfs(vs[0])
232 # See if all nodes have been visited 234 # See if all nodes have been visited
233 for v in vs: 235 return len(vs) == len(visited)
234 if not v.visited:
235 return False
236 return True
237 236
238 return False # Graph is empty 237 return False # Graph is empty
239 238
240 239
241 def main(script, *args): 240 def main(script, *args):