Implementing Breadth-First Search
Distance, precisely
Here’s the algorithm we ended up with last time:
function distance(start, end): distance to start = 0 to-visit = [start] while nodes in to-visit: node = first node from to-visit for neighbor in neighbors: if we haven't yet set neighbor's distance: distance to neighbor = distance to node + 1 if neighbor == end: return distance to neighbor add neighbor to to-visit return Infinity
How can we make this a bit more concrete? We’ll need to figure out how to track the
distances, and what data structure to use as the to-visit
queue.
One possibility (among others!) would be to use a dictionary for the distances and a list for the queue. Then we could write something like this:
function distance(graph, start, end): distances = {start: 0} to-visit = [start] while not to-visit is empty: node = to-visit.head to-visit = to-visit.tail for neighbor in graph.neighbors(start): if neighbor not in distances: distances[neighbor] = distance[node] + 1 if neighbor == end: return distances[neighbor] to-visit = to-visit + [neighbor] return Infinity
Implementing distance
In order to implement our distance algorithm, we need a graph! We could
implement it on the social graph included with the project; I’m implementing it
with a FlightGraph
class I’ve made for this purpose. Our Scala implementation
ends up looking like this:
def distance(graph: FlightGraph, start: String, end: String): Int = { var distances = Map(start -> 0) var visit = List(start) while (!visit.isEmpty) { val node = visit.head visit = visit.tail for (neighbor <- graph.neighbors(node)) { if (!distances.contains(neighbor)) { distances = distances + (neighbor -> (distances(node) + 1)) if (neighbor == end) { return distances(neighbor) } visit = visit :+ neighbor } } } -1 }
The breadth-first search algorithm we see here can be used to solve any problem where we need to visit all of the nodes we can get to from a starting node, in order of how far away we are. The important properties of breadth-first search are that:
- It visits every node in order of the number of edges it is from the starting
node (this is guaranteed by the
visit
queue) - It only visits a node once (this is guaranteed by the
if (!distances.contains(neighbor))
check).