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).