# Source code for tryalgo.bfs

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""\
Breadth-first search (bfs)
christoph dürr - jill-jênn vie - 2015-2019, 2023
"""
# snip{
from collections import deque
[docs]
def bfs(graph, start=0):
"""Shortest path in unweighted graph by BFS
:param graph: directed graph in listlist or listdict format
:param int start: source vertex
:returns: distance table, precedence table
:complexity: `O(|V|+|E|)`
"""
to_visit = deque()
dist = [float('inf')] * len(graph)
prec = [None] * len(graph)
dist[start] = 0
to_visit.appendleft(start)
while to_visit: # an empty queue is considered False
node = to_visit.pop()
for neighbor in graph[node]:
if dist[neighbor] == float('inf'):
dist[neighbor] = dist[node] + 1
prec[neighbor] = node
to_visit.appendleft(neighbor)
return dist, prec
# snip}
[docs]
def bfs_implicit(graph, start, end):
"""Shortest path by BFS in an implicitly directed graph
:param graph: function mapping a given vertex to
an iterator over the neighboring vertices
:param start: source vertex
:param end: target vertex
:returns: list of vertices of a shortest path or None
:complexity: `O(|V|+|E|)`
"""
to_visit = deque()
prec = {start: None} # predecessor on shortest path
to_visit.appendleft(start)
while to_visit:
node = to_visit.pop()
for neighbor in graph(node):
if neighbor not in prec: # not yet discovered
prec[neighbor] = node
to_visit.appendleft(neighbor)
if end in prec:
# solution found
L = [end] # backtrack the shortest path
while prec[L[-1]] is not None:
L.append(prec[L[-1]])
return L[::-1] # return in start to end order
return None