// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea // Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology // Distributed under the terms of the GNU Lesser General Public License (LGPL): http://www.gnu.org/licenses/ /* * DepthFirstSearch.java * * Created on November 20, 2004, 10:31 PM */ package graphtea.library.algorithms.traversal; import graphtea.library.BaseEdge; import graphtea.library.BaseGraph; import graphtea.library.BaseVertex; import graphtea.library.algorithms.Algorithm; import graphtea.library.algorithms.AutomatedAlgorithm; import graphtea.library.algorithms.util.EventUtils; import graphtea.library.event.GraphRequest; import graphtea.library.event.PostWorkEvent; import graphtea.library.event.PreWorkEvent; import graphtea.library.event.VertexRequest; import graphtea.library.event.handlers.PreWorkPostWorkHandler; import graphtea.library.exceptions.InvalidGraphException; import graphtea.library.exceptions.InvalidVertexException; /** * @author Omid Aladini */ public class DepthFirstSearch<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> extends Algorithm implements AutomatedAlgorithm { private BaseGraph<VertexType, EdgeType> graph; public DepthFirstSearch(BaseGraph<VertexType, EdgeType> graph) { this.graph = graph; } public DepthFirstSearch() { this.graph = null; } /** * Calling this will not reset the marks. * * @param vertex Index of the starting vertex of the traversal. * @param handler A reference to a PreWorkPostWorkHandler that contains implementation * of pre-work and post-work operations that depends on the application of DFS. * @return Whether the traversal has stopped at the middle by the handler. */ public boolean doSearch(VertexType vertex, PreWorkPostWorkHandler<VertexType> handler) { return doSearch(vertex, handler, true); } /** * Runs Depth First Search (DFS) algorithm on the graph starting from vertex <I>vertexId</I>. * A reference to a PreWorkPostWorkHandler is supplied that contains implementation * of pre-work and post-work operations that depends on the application of DFS. * * @param vertex Index of the starting vertex of the traversal. * @param handler A reference to a PreWorkPostWorkHandler that contains implementation * of pre-work and post-work operations that depends on the application of DFS. * @param resetMarks If the search should reset vertex visit marks. * @return Whether the traversal has stopped at the middle by the handler. */ public boolean doSearch(VertexType vertex, PreWorkPostWorkHandler<VertexType> handler, boolean resetMarks) throws InvalidVertexException, InvalidGraphException { if (graph == null) throw new InvalidGraphException("Graph object is null."); if (resetMarks) for (VertexType v : graph) v.setMark(false); return depthFirstSearchRecursive(vertex, vertex, handler); } private boolean depthFirstSearchRecursive(VertexType vertex, VertexType fromVertex, PreWorkPostWorkHandler<VertexType> handler) throws InvalidVertexException { //TODO:Implementing non-recursive version //int vertexId = vertex.getId(); vertex.setMark(true); if (handler != null) if (handler.doPreWork(fromVertex, vertex)) return true; dispatchEvent(new PreWorkEvent<>(fromVertex, vertex, graph)); EventUtils.algorithmStep(this, "visit: " + vertex.getId()); VertexType lastInDepthVertex = vertex; for (VertexType i : graph) { if (graph.isEdge(vertex, i)) { if (!i.getMark()) { lastInDepthVertex = i; if (depthFirstSearchRecursive(i, vertex, handler)) return true; } } } dispatchEvent(new PostWorkEvent<>(lastInDepthVertex, vertex, graph)); EventUtils.algorithmStep(this, "leave: " + vertex.getId()); if (handler != null) if (handler.doPostWork(lastInDepthVertex, vertex)) return true; return false; } public void doAlgorithm() { GraphRequest<VertexType, EdgeType> gr = new GraphRequest<>(); dispatchEvent(gr); this.graph = gr.getGraph(); VertexRequest<VertexType, EdgeType> vr = new VertexRequest<>(graph, "Please choose a vertex for the DFS algorithm."); dispatchEvent(vr); this.doSearch(vr.getVertex(), null); } }