K_K
K_K

Reputation: 51

Python DFS and BFS

Here http://www.python.org/doc/essays/graphs/ is DFS right ?

I try to do something with 'siblings', but it does not work. Can anyone write BFS similar to code from this site.

Upvotes: 5

Views: 19231

Answers (3)

user8613903
user8613903

Reputation: 11

def recursive_dfs(graph, start, path=[]):
  '''recursive depth first search from start'''
  path=path+[start]
  for node in graph[start]:
    if not node in path:
      path=recursive_dfs(graph, node, path)
  return path

def iterative_dfs(graph, start, path=[]):
  '''iterative depth first search from start'''
  q=[start]
  while q:
    v=q.pop(0)
    if v not in path:
      path=path+[v]
      q=graph[v]+q
  return path

def iterative_bfs(graph, start, path=[]):
  '''iterative breadth first search from start'''
  q=[start]
  while q:
    v=q.pop(0)
    if not v in path:
      path=path+[v]
      q=q+graph[v]
  return path

'''
   +---- A
   |   /   \
   |  B--D--C
   |   \ | /
   +---- E
'''
graph = {'A':['B','C'],'B':['D','E'],'C':['D','E'],'D':['E'],'E':['A']}
print 'recursive dfs ', recursive_dfs(graph, 'A')
print 'iterative dfs ', iterative_dfs(graph, 'A')
print 'iterative bfs ', iterative_bfs(graph, 'A')

Upvotes: 1

user97370
user97370

Reputation:

Here's an O(N * max(vertex degree)) breadth-first search implementation. The bfs function generates nodes in breadth-first order, and for each a generator that can be used to trace a shortest path back to the start point. The lazy nature of the paths means that you can iterate through the generated node to find points you're interested in without paying the cost of building all the intermediate paths.

import collections

GRAPH = {'A': ['B', 'C'],
         'B': ['C', 'D'],
         'C': ['D'],
         'D': ['C'],
         'E': ['F'],
         'F': ['C']}

def build_path(node, previous_map):
    while node:
        yield node
        node = previous_map.get(node)

def bfs(start, graph):
    previous_map = {}
    todo = collections.deque()
    todo.append(start)
    while todo:
        node = todo.popleft()
        yield node, build_path(node, previous)
        for next_node in graph.get(node, []):
            if next_node not in previous_map:
                previous_map[next_node] = node
                todo.append(next_node)

for node, path in bfs('A', GRAPH):
    print node, list(path)

Upvotes: 1

btilly
btilly

Reputation: 46507

Yes, it is DFS.

To write a BFS you just need to keep a "todo" queue. You probably also want to turn the function into a generator because often a BFS is deliberately ended before it generates all possible paths. Thus this function can be used to be find_path or find_all_paths.

def paths(graph, start, end):
    todo = [[start, [start]]]
    while 0 < len(todo):
        (node, path) = todo.pop(0)
        for next_node in graph[node]:
            if next_node in path:
                continue
            elif next_node == end:
                yield path + [next_node]
            else:
                todo.append([next_node, path + [next_node]])

And an example of how to use it:

graph = {'A': ['B', 'C'],
         'B': ['C', 'D'],
         'C': ['D'],
         'D': ['C'],
         'E': ['F'],
         'F': ['C']}

for path in paths(graph, 'A', 'D'):
    print path

Upvotes: 8

Related Questions