graph->getVertices()->isEmpty()) { return false; } // every vertex can represent a root vertex, so just pick one $root = $this->graph->getVertices()->getVertexFirst(); $vertices = array(); try { $this->getVerticesSubtreeRecursive($root, $vertices, null); } catch (UnexpectedValueException $e) { return false; } return (count($vertices) === count($this->graph->getVertices())); } /** * checks if the given $vertex is a leaf (outermost vertex with exactly one edge) * * @param Vertex $vertex * @return boolean * @uses Degree::getDegreeVertex() */ public function isVertexLeaf(Vertex $vertex) { return ($this->degree->getDegreeVertex($vertex) === 1); } /** * checks if the given $vertex is an internal vertex (inner vertex with at least 2 edges) * * @param Vertex $vertex * @return boolean * @uses Degree::getDegreeVertex() */ public function isVertexInternal(Vertex $vertex) { return ($this->degree->getDegreeVertex($vertex) >= 2); } /** * get subtree for given Vertex and ignore path to "parent" ignoreVertex * * @param Vertex $vertex * @param Vertex[] $vertices * @param Vertex|null $ignore * @throws UnexpectedValueException for cycles or directed edges (check isTree()!) * @uses self::getVerticesNeighbor() * @uses self::getVerticesSubtreeRecursive() to recurse into sub-subtrees */ private function getVerticesSubtreeRecursive(Vertex $vertex, array &$vertices, Vertex $ignore = null) { if (isset($vertices[$vertex->getId()])) { // vertex already visited => must be a cycle throw new UnexpectedValueException('Vertex already visited'); } $vertices[$vertex->getId()] = $vertex; foreach ($this->getVerticesNeighbor($vertex) as $vertexNeighboor) { if ($vertexNeighboor === $ignore) { // ignore source vertex only once $ignore = null; continue; } $this->getVerticesSubtreeRecursive($vertexNeighboor, $vertices, $vertex); } } /** * get neighbor vertices for given start vertex * * @param Vertex $vertex * @throws UnexpectedValueException for directed edges * @return Vertices (might include possible duplicates) * @uses Vertex::getEdges() * @uses Edge::getVertexToFrom() * @see Vertex::getVerticesEdge() */ private function getVerticesNeighbor(Vertex $vertex) { $vertices = array(); foreach ($vertex->getEdges() as $edge) { /* @var Edge $edge */ if (!($edge instanceof UndirectedEdge)) { throw new UnexpectedValueException('Directed edge encountered'); } $vertices[] = $edge->getVertexToFrom($vertex); } return new Vertices($vertices); } }