src/Algo/BFS.php
<?php
/**
* Breadth-first search.
*/
namespace GraphDS\Algo;
use GraphDS\Graph\Graph;
use GraphDS\Graph\DirectedGraph;
use GraphDS\Graph\UndirectedGraph;
use InvalidArgumentException;
use SplQueue;
/**
* Class defining the breadth-first search.
*/
class BFS
{
/**
* Reference to the graph.
*
* @var Graph
*/
public $graph;
/**
* Distances for each node to root in hops.
*
* @var array
*/
public $dist;
/**
* Parents for each vertex.
*
* @var array
*/
public $parent;
/**
* Discovered vertices, in BFS order.
*
* @var array
*/
public $discovered;
/**
* Constructor for the BFS algorithm.
*
* @param Graph $graph The graph to which the BFS algorithm should be applied
*/
public function __construct(Graph $graph)
{
if (!($graph instanceof DirectedGraph) && !($graph instanceof UndirectedGraph)) {
throw new InvalidArgumentException(
"Breadth-first search algorithm requires a directed or undirected graph"
);
}
$this->graph = &$graph;
$this->dist = array();
$this->parent = array();
$this->discovered = array();
}
/**
* Runs the BFS from a given vertex $vertex on the graph.
*
* @param mixed $root ID of the vertex from which the BFS should begin
*/
public function run($root)
{
foreach (array_keys($this->graph->vertices) as $vertex) {
$this->dist[$vertex] = INF;
$this->parent[$vertex] = null;
}
$this->discovered = array();
$queue = new SplQueue();
$this->dist[$root] = 0;
$queue->enqueue($root);
while (!$queue->isEmpty()) {
$this->discovered[] = $current = $queue->dequeue();
if ($this->graph instanceof UndirectedGraph) {
$neighbors = $this->graph->vertices[$current]->getNeighbors();
} elseif ($this->graph instanceof DirectedGraph) {
$neighbors = $this->graph->vertices[$current]->getOutNeighbors();
}
foreach ($neighbors as $vertex) {
if ($this->dist[$vertex] == INF) {
$this->dist[$vertex] = $this->dist[$current] + 1;
$this->parent[$vertex] = $current;
$queue->enqueue($vertex);
}
}
}
}
/**
* Returns the result of the BFS.
*
* @return array Array of vertex distance to root, parents and vertices in BFS order
*/
public function get()
{
return array(
'dist' => $this->dist,
'parent' => $this->parent,
'discovered' => $this->discovered,
);
}
}