Breadth First Paths Algorithm

The Breadth First Paths Algorithm is a graph traversal algorithm used to explore all the vertices and edges of a graph systematically by visiting all the vertices at a given level before moving on to the next level. This algorithm is particularly useful for finding the shortest path between two vertices in an unweighted graph or for determining the minimum number of steps required to reach a destination. It starts at the source vertex and proceeds by visiting all its adjacent vertices, then all the vertices adjacent to those, and so on. The algorithm maintains a queue to keep track of the vertices to be visited and a boolean array to mark the visited vertices to avoid revisiting them. The main idea behind the Breadth First Paths Algorithm is to use a breadth-first search (BFS) strategy, which explores the vertices in increasing order of their distance from the source vertex. In each step, the algorithm dequeues the next vertex from the queue, visits it, and then enqueues all its unvisited neighbors. This process continues until the queue is empty or the destination vertex is encountered. To reconstruct the shortest path, the algorithm also maintains an array of edge-to vertices, which keeps track of the vertices that lead to the current vertex in the shortest path. This enables the algorithm to trace back the path from the destination vertex to the source vertex once the traversal is complete. The Breadth First Paths Algorithm is efficient and guarantees the optimality of the solution, making it an essential tool for solving a wide range of graph-related problems.
package org.gs.graph

import scala.annotation.tailrec
import scala.collection.mutable.{ListBuffer, Queue}

/** Find shortest path from source vertex to v
  *
  * Enqueue a vertex that has been marked but its adjacencies haven't been. Then dequeue a vertex and
  * enqueue all its unmarked adjacencies and mark them
  *
  * @constructor creates a new BreadthFirstPaths with a graph and source vertex
  * @param g Graph
  * @param s source vertex
  * @see [[https://algs4.cs.princeton.edu/41undirected/BreadthFirstPaths.java.html]]
  * @author Scala translation by Gary Struthers from Java by Robert Sedgewick and Kevin Wayne.
  */
class BreadthFirstPaths(g: Graph, s: Int) {
  private[graph] val marked = Array.fill[Boolean](g.numV)(false)
  private[graph] val edgeTo = new Array[Int](g.numV)
  private[graph] val _distTo = Array.fill[Int](g.numV)(Int.MaxValue)

  private def bfs(s: Int): Unit = {
    _distTo(s) = 0
    marked(s) = true

    @tailrec
    def loop(q: Queue[Int]): Unit = if (!q.isEmpty) {
      val v = q.dequeue
      g.adj(v) foreach (w => if (!marked(w)) {
        edgeTo(w) = v
        _distTo(w) = _distTo(v) + 1
        marked(w) = true
        q.enqueue(w)
      })
      loop(q)
    }

    loop(Queue[Int](s))
  }

  bfs(s)

  /** is there a path from source vertex s to v */
  def hasPathTo(v: Int): Boolean = marked(v)

  /** returns number of edges in shortest path from source vertex to v */
  def distTo(v: Int): Int = _distTo(v)

  /** returns a list of vertices in the shortest path from the source vertex to v */
  def pathTo(v: Int): Option[List[Int]] = if (!hasPathTo(v)) None else {

    @tailrec
    def loop(x: Int, xs: List[Int]): List[Int] = if (distTo(x) != 0) loop(edgeTo(x), x :: xs) else x :: xs

    Some(loop(v, List[Int]()))
  }
}

LANGUAGE:

DARK MODE: