Gliph\Traversal\DepthFirst::traverse PHP Méthode

traverse() public static méthode

Perform a depth-first traversal on the provided graph.
public static traverse ( Gliph\Graph\Digraph $graph, Gliph\Visitor\DepthFirstVisitorInterface $visitor, object | SplDoublyLinkedList $start = NULL )
$graph Gliph\Graph\Digraph The graph on which to perform the depth-first search.
$visitor Gliph\Visitor\DepthFirstVisitorInterface The visitor object to use during the traversal.
$start object | SplDoublyLinkedList A vertex, or vertices, to use as start points for the traversal. There are a few sub-behaviors here: - If an SplDoublyLinkedList, SplQueue, or SplStack is provided, the traversal will deque and visit vertices contained therein. - If a single vertex object is provided, it will be the sole originating point for the traversal. - If no value is provided, DepthFirst::find_sources() is called to search the graph for source vertices. These are place into an SplQueue in the order in which they are discovered, and traversal is then run over that queue in the same manner as if calling code had provided a queue directly. This method *guarantees* that all vertices in the graph will be visited.
    public static function traverse(Digraph $graph, DepthFirstVisitorInterface $visitor, $start = NULL)
    {
        if ($start === NULL) {
            $queue = self::find_sources($graph, $visitor);
        } else {
            if ($start instanceof \SplDoublyLinkedList) {
                $queue = $start;
            } else {
                if (is_object($start)) {
                    $queue = new \SplDoublyLinkedList();
                    $queue->push($start);
                }
            }
        }
        if ($queue->isEmpty()) {
            throw new RuntimeException('No start vertex or vertices were provided, and no source vertices could be found in the provided graph.', E_WARNING);
        }
        $visiting = new \SplObjectStorage();
        $visited = new \SplObjectStorage();
        $visitor->beginTraversal();
        $visit = function ($vertex) use($graph, $visitor, &$visit, $visiting, $visited) {
            if ($visiting->contains($vertex)) {
                $visitor->onBackEdge($vertex, $visit);
            } else {
                if (!$visited->contains($vertex)) {
                    $visiting->attach($vertex);
                    $visitor->onStartVertex($vertex, $visit);
                    foreach ($graph->successorsOf($vertex) as $head) {
                        $visitor->onExamineEdge($vertex, $head, $visit);
                        $visit($head);
                    }
                    $visitor->onFinishVertex($vertex, $visit);
                    $visiting->detach($vertex);
                    $visited->attach($vertex);
                }
            }
        };
        // TODO experiment with adding a generator-producing visitor method that yields the queue here
        while (!$queue->isEmpty()) {
            $vertex = $queue->shift();
            $visit($vertex);
        }
        $visitor->endTraversal();
    }

Usage Example

 /**
  * {@inheritdoc}
  */
 public function isAcyclic()
 {
     // The DepthFirstToposortVisitor throws an exception on cycles.
     try {
         DepthFirst::traverse($this, new DepthFirstToposortVisitor());
         return TRUE;
     } catch (RuntimeException $e) {
         return FALSE;
     }
 }
All Usage Examples Of Gliph\Traversal\DepthFirst::traverse