/* * This file is part of the Trickl Open Source Libraries. * * Trickl Open Source Libraries - http://open.trickl.com/ * * Copyright (C) 2011 Tim Gee. * * Trickl Open Source Libraries are free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Trickl Open Source Libraries are distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this project. If not, see <http://www.gnu.org/licenses/>. */ package com.trickl.graph; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.jgrapht.Graph; public class BreadthFirstSearch<V, E> { private enum Color { WHITE, GRAY, BLACK; } LinkedList<V> order = new LinkedList<V>(); private Graph<V, E> graph; public BreadthFirstSearch(Graph<V, E> graph) { this.graph = graph; } public void traverse(SpanningSearchVisitor<V, E> visitor) { Iterator<V> vertexIterator = graph.vertexSet().iterator(); if (vertexIterator.hasNext()) { traverse(vertexIterator.next(), visitor); } } public void traverse(V startVertex, SpanningSearchVisitor<V, E> visitor) { // Initialize the color map Map<V, Color> colorMap = new HashMap<V, Color>(graph.vertexSet().size()); for (V u : graph.vertexSet()) { colorMap.put(u, Color.WHITE); visitor.initializeVertex(u); } visitor.startVertex(startVertex); order.clear(); traverseImpl(startVertex, visitor, colorMap); // The graph may be disconnected - search untouched disjoint sets for (V u : graph.vertexSet()) { Color color = colorMap.get(u); if (color == Color.WHITE) { visitor.startVertex(u); order.clear(); traverseImpl(u, visitor, colorMap); } } } private void traverseImpl(V startVertex, SpanningSearchVisitor<V, E> visitor, Map<V, Color> colorMap) { V u = startVertex; colorMap.put(u, Color.GRAY); visitor.discoverVertex(u); order.add(u); while (!order.isEmpty()) { u = order.poll(); Iterator<E> edgeItr = graph.edgesOf(u).iterator(); while (edgeItr.hasNext()) { E e = edgeItr.next(); V v = graph.getEdgeTarget(e).equals(u) ? graph.getEdgeSource(e) : graph.getEdgeTarget(e); // Check if a directed edge in the wrong direction if (!graph.containsEdge(u, v)) continue; visitor.examineEdge(u, v); Color color = colorMap.get(v); if (color == Color.WHITE) { visitor.discoverVertex(v); visitor.treeEdge(u, v); order.add(v); colorMap.put(v, Color.GRAY); } else if (color == Color.GRAY) { visitor.backEdge(u, v); } else { visitor.forwardOrCrossEdge(u, v); } } colorMap.put(u, Color.BLACK); visitor.finishVertex(u); } } }