Mega Code Archive

 
Categories / Java / Collections Data Structure
 

A directed graph data structure

/*  * JBoss, Home of Professional Open Source  * Copyright 2006, Red Hat Middleware LLC, and individual contributors  * by the @authors tag. See the copyright.txt in the distribution for a  * full listing of individual contributors.  *  * This is free software; you can redistribute it and/or modify it  * under the terms of the GNU Lesser General Public License as  * published by the Free Software Foundation; either version 2.1 of  * the License, or (at your option) any later version.  *  * This software is 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  * Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public  * License along with this software; if not, write to the Free  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.  */ import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedList; import java.util.List; /**  * A directed graph data structure.  *   * @author Scott.Stark@jboss.org  * @version $Revision$  * @param <T>  */ @SuppressWarnings("unchecked") public class Graph<T> {   /** Color used to mark unvisited nodes */   public static final int VISIT_COLOR_WHITE = 1;   /** Color used to mark nodes as they are first visited in DFS order */   public static final int VISIT_COLOR_GREY = 2;   /** Color used to mark nodes after descendants are completely visited */   public static final int VISIT_COLOR_BLACK = 3;   /** Vector<Vertex> of graph verticies */   private List<Vertex<T>> verticies;   /** Vector<Edge> of edges in the graph */   private List<Edge<T>> edges;   /** The vertex identified as the root of the graph */   private Vertex<T> rootVertex;   /**    * Construct a new graph without any vertices or edges    */   public Graph() {     verticies = new ArrayList<Vertex<T>>();     edges = new ArrayList<Edge<T>>();   }   /**    * Are there any verticies in the graph    *     * @return true if there are no verticies in the graph    */   public boolean isEmpty() {     return verticies.size() == 0;   }   /**    * Add a vertex to the graph    *     * @param v    *          the Vertex to add    * @return true if the vertex was added, false if it was already in the graph.    */   public boolean addVertex(Vertex<T> v) {     boolean added = false;     if (verticies.contains(v) == false) {       added = verticies.add(v);     }     return added;   }   /**    * Get the vertex count.    *     * @return the number of verticies in the graph.    */   public int size() {     return verticies.size();   }   /**    * Get the root vertex    *     * @return the root vertex if one is set, null if no vertex has been set as    *         the root.    */   public Vertex<T> getRootVertex() {     return rootVertex;   }   /**    * Set a root vertex. If root does no exist in the graph it is added.    *     * @param root -    *          the vertex to set as the root and optionally add if it does not    *          exist in the graph.    */   public void setRootVertex(Vertex<T> root) {     this.rootVertex = root;     if (verticies.contains(root) == false)       this.addVertex(root);   }   /**    * Get the given Vertex.    *     * @param n    *          the index [0, size()-1] of the Vertex to access    * @return the nth Vertex    */   public Vertex<T> getVertex(int n) {     return verticies.get(n);   }   /**    * Get the graph verticies    *     * @return the graph verticies    */   public List<Vertex<T>> getVerticies() {     return this.verticies;   }   /**    * Insert a directed, weighted Edge<T> into the graph.    *     * @param from -    *          the Edge<T> starting vertex    * @param to -    *          the Edge<T> ending vertex    * @param cost -    *          the Edge<T> weight/cost    * @return true if the Edge<T> was added, false if from already has this Edge<T>    * @throws IllegalArgumentException    *           if from/to are not verticies in the graph    */   public boolean addEdge(Vertex<T> from, Vertex<T> to, int cost) throws IllegalArgumentException {     if (verticies.contains(from) == false)       throw new IllegalArgumentException("from is not in graph");     if (verticies.contains(to) == false)       throw new IllegalArgumentException("to is not in graph");     Edge<T> e = new Edge<T>(from, to, cost);     if (from.findEdge(to) != null)       return false;     else {       from.addEdge(e);       to.addEdge(e);       edges.add(e);       return true;     }   }   /**    * Insert a bidirectional Edge<T> in the graph    *     * @param from -    *          the Edge<T> starting vertex    * @param to -    *          the Edge<T> ending vertex    * @param cost -    *          the Edge<T> weight/cost    * @return true if edges between both nodes were added, false otherwise    * @throws IllegalArgumentException    *           if from/to are not verticies in the graph    */   public boolean insertBiEdge(Vertex<T> from, Vertex<T> to, int cost)       throws IllegalArgumentException {     return addEdge(from, to, cost) && addEdge(to, from, cost);   }   /**    * Get the graph edges    *     * @return the graph edges    */   public List<Edge<T>> getEdges() {     return this.edges;   }   /**    * Remove a vertex from the graph    *     * @param v    *          the Vertex to remove    * @return true if the Vertex was removed    */   public boolean removeVertex(Vertex<T> v) {     if (!verticies.contains(v))       return false;     verticies.remove(v);     if (v == rootVertex)       rootVertex = null;     // Remove the edges associated with v     for (int n = 0; n < v.getOutgoingEdgeCount(); n++) {       Edge<T> e = v.getOutgoingEdge(n);       v.remove(e);       Vertex<T> to = e.getTo();       to.remove(e);       edges.remove(e);     }     for (int n = 0; n < v.getIncomingEdgeCount(); n++) {       Edge<T> e = v.getIncomingEdge(n);       v.remove(e);       Vertex<T> predecessor = e.getFrom();       predecessor.remove(e);     }     return true;   }   /**    * Remove an Edge<T> from the graph    *     * @param from -    *          the Edge<T> starting vertex    * @param to -    *          the Edge<T> ending vertex    * @return true if the Edge<T> exists, false otherwise    */   public boolean removeEdge(Vertex<T> from, Vertex<T> to) {     Edge<T> e = from.findEdge(to);     if (e == null)       return false;     else {       from.remove(e);       to.remove(e);       edges.remove(e);       return true;     }   }   /**    * Clear the mark state of all verticies in the graph by calling clearMark()    * on all verticies.    *     * @see Vertex#clearMark()    */   public void clearMark() {     for (Vertex<T> w : verticies)       w.clearMark();   }   /**    * Clear the mark state of all edges in the graph by calling clearMark() on    * all edges.    */   public void clearEdges() {     for (Edge<T> e : edges)       e.clearMark();   }   /**    * Perform a depth first serach using recursion.    *     * @param v -    *          the Vertex to start the search from    * @param visitor -    *          the vistor to inform prior to    * @see Visitor#visit(Graph, Vertex)    */   public void depthFirstSearch(Vertex<T> v, final Visitor<T> visitor) {     VisitorEX<T, RuntimeException> wrapper = new VisitorEX<T, RuntimeException>() {       public void visit(Graph<T> g, Vertex<T> v) throws RuntimeException {         if (visitor != null)           visitor.visit(g, v);       }     };     this.depthFirstSearch(v, wrapper);   }   /**    * Perform a depth first serach using recursion. The search may be cut short    * if the visitor throws an exception.    *     * @param <E>    *     * @param v -    *          the Vertex to start the search from    * @param visitor -    *          the vistor to inform prior to    * @see Visitor#visit(Graph, Vertex)    * @throws E    *           if visitor.visit throws an exception    */   public <E extends Exception> void depthFirstSearch(Vertex<T> v, VisitorEX<T, E> visitor) throws E {     if (visitor != null)       visitor.visit(this, v);     v.visit();     for (int i = 0; i < v.getOutgoingEdgeCount(); i++) {       Edge<T> e = v.getOutgoingEdge(i);       if (!e.getTo().visited()) {         depthFirstSearch(e.getTo(), visitor);       }     }   }   /**    * Perform a breadth first search of this graph, starting at v.    *     * @param v -    *          the search starting point    * @param visitor -    *          the vistor whose vist method is called prior to visting a vertex.    */   public void breadthFirstSearch(Vertex<T> v, final Visitor<T> visitor) {     VisitorEX<T, RuntimeException> wrapper = new VisitorEX<T, RuntimeException>() {       public void visit(Graph<T> g, Vertex<T> v) throws RuntimeException {         if (visitor != null)           visitor.visit(g, v);       }     };     this.breadthFirstSearch(v, wrapper);   }   /**    * Perform a breadth first search of this graph, starting at v. The vist may    * be cut short if visitor throws an exception during a vist callback.    *     * @param <E>    *     * @param v -    *          the search starting point    * @param visitor -    *          the vistor whose vist method is called prior to visting a vertex.    * @throws E    *           if vistor.visit throws an exception    */   public <E extends Exception> void breadthFirstSearch(Vertex<T> v, VisitorEX<T, E> visitor)       throws E {     LinkedList<Vertex<T>> q = new LinkedList<Vertex<T>>();     q.add(v);     if (visitor != null)       visitor.visit(this, v);     v.visit();     while (q.isEmpty() == false) {       v = q.removeFirst();       for (int i = 0; i < v.getOutgoingEdgeCount(); i++) {         Edge<T> e = v.getOutgoingEdge(i);         Vertex<T> to = e.getTo();         if (!to.visited()) {           q.add(to);           if (visitor != null)             visitor.visit(this, to);           to.visit();         }       }     }   }   /**    * Find the spanning tree using a DFS starting from v.    *     * @param v -    *          the vertex to start the search from    * @param visitor -    *          visitor invoked after each vertex is visited and an edge is added    *          to the tree.    */   public void dfsSpanningTree(Vertex<T> v, DFSVisitor<T> visitor) {     v.visit();     if (visitor != null)       visitor.visit(this, v);     for (int i = 0; i < v.getOutgoingEdgeCount(); i++) {       Edge<T> e = v.getOutgoingEdge(i);       if (!e.getTo().visited()) {         if (visitor != null)           visitor.visit(this, v, e);         e.mark();         dfsSpanningTree(e.getTo(), visitor);       }     }   }   /**    * Search the verticies for one with name.    *     * @param name -    *          the vertex name    * @return the first vertex with a matching name, null if no matches are found    */   public Vertex<T> findVertexByName(String name) {     Vertex<T> match = null;     for (Vertex<T> v : verticies) {       if (name.equals(v.getName())) {         match = v;         break;       }     }     return match;   }   /**    * Search the verticies for one with data.    *     * @param data -    *          the vertex data to match    * @param compare -    *          the comparator to perform the match    * @return the first vertex with a matching data, null if no matches are found    */   public Vertex<T> findVertexByData(T data, Comparator<T> compare) {     Vertex<T> match = null;     for (Vertex<T> v : verticies) {       if (compare.compare(data, v.getData()) == 0) {         match = v;         break;       }     }     return match;   }   /**    * Search the graph for cycles. In order to detect cycles, we use a modified    * depth first search called a colored DFS. All nodes are initially marked    * white. When a node is encountered, it is marked grey, and when its    * descendants are completely visited, it is marked black. If a grey node is    * ever encountered, then there is a cycle.    *     * @return the edges that form cycles in the graph. The array will be empty if    *         there are no cycles.    */   public Edge<T>[] findCycles() {     ArrayList<Edge<T>> cycleEdges = new ArrayList<Edge<T>>();     // Mark all verticies as white     for (int n = 0; n < verticies.size(); n++) {       Vertex<T> v = getVertex(n);       v.setMarkState(VISIT_COLOR_WHITE);     }     for (int n = 0; n < verticies.size(); n++) {       Vertex<T> v = getVertex(n);       visit(v, cycleEdges);     }     Edge<T>[] cycles = new Edge[cycleEdges.size()];     cycleEdges.toArray(cycles);     return cycles;   }   private void visit(Vertex<T> v, ArrayList<Edge<T>> cycleEdges) {     v.setMarkState(VISIT_COLOR_GREY);     int count = v.getOutgoingEdgeCount();     for (int n = 0; n < count; n++) {       Edge<T> e = v.getOutgoingEdge(n);       Vertex<T> u = e.getTo();       if (u.getMarkState() == VISIT_COLOR_GREY) {         // A cycle Edge<T>         cycleEdges.add(e);       } else if (u.getMarkState() == VISIT_COLOR_WHITE) {         visit(u, cycleEdges);       }     }     v.setMarkState(VISIT_COLOR_BLACK);   }   public String toString() {     StringBuffer tmp = new StringBuffer("Graph[");     for (Vertex<T> v : verticies)       tmp.append(v);     tmp.append(']');     return tmp.toString();   } } /*  * JBoss, Home of Professional Open Source Copyright 2006, Red Hat Middleware  * LLC, and individual contributors by the @authors tag. See the copyright.txt  * in the distribution for a full listing of individual contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is 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 Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * A directed, weighted edge in a graph  *   * @author Scott.Stark@jboss.org  * @version $Revision$  * @param <T>  */ class Edge<T> {   private Vertex<T> from;   private Vertex<T> to;   private int cost;   private boolean mark;   /**    * Create a zero cost edge between from and to    *     * @param from    *          the starting vertex    * @param to    *          the ending vertex    */   public Edge(Vertex<T> from, Vertex<T> to) {     this(from, to, 0);   }   /**    * Create an edge between from and to with the given cost.    *     * @param from    *          the starting vertex    * @param to    *          the ending vertex    * @param cost    *          the cost of the edge    */   public Edge(Vertex<T> from, Vertex<T> to, int cost) {     this.from = from;     this.to = to;     this.cost = cost;     mark = false;   }   /**    * Get the ending vertex    *     * @return ending vertex    */   public Vertex<T> getTo() {     return to;   }   /**    * Get the starting vertex    *     * @return starting vertex    */   public Vertex<T> getFrom() {     return from;   }   /**    * Get the cost of the edge    *     * @return cost of the edge    */   public int getCost() {     return cost;   }   /**    * Set the mark flag of the edge    *     */   public void mark() {     mark = true;   }   /**    * Clear the edge mark flag    *     */   public void clearMark() {     mark = false;   }   /**    * Get the edge mark flag    *     * @return edge mark flag    */   public boolean isMarked() {     return mark;   }   /**    * String rep of edge    *     * @return string rep with from/to vertex names and cost    */   public String toString() {     StringBuffer tmp = new StringBuffer("Edge[from: ");     tmp.append(from.getName());     tmp.append(",to: ");     tmp.append(to.getName());     tmp.append(", cost: ");     tmp.append(cost);     tmp.append("]");     return tmp.toString();   } } /*  * JBoss, Home of Professional Open Source Copyright 2006, Red Hat Middleware  * LLC, and individual contributors by the @authors tag. See the copyright.txt  * in the distribution for a full listing of individual contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is 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 Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * A named graph vertex with optional data.  *   * @author Scott.Stark@jboss.org  * @version $Revision$  * @param <T>  */ @SuppressWarnings("unchecked") class Vertex<T> {   private List<Edge<T>> incomingEdges;   private List<Edge<T>> outgoingEdges;   private String name;   private boolean mark;   private int markState;   private T data;   /**    * Calls this(null, null).    */   public Vertex() {     this(null, null);   }   /**    * Create a vertex with the given name and no data    *     * @param n    */   public Vertex(String n) {     this(n, null);   }   /**    * Create a Vertex with name n and given data    *     * @param n -    *          name of vertex    * @param data -    *          data associated with vertex    */   public Vertex(String n, T data) {     incomingEdges = new ArrayList<Edge<T>>();     outgoingEdges = new ArrayList<Edge<T>>();     name = n;     mark = false;     this.data = data;   }   /**    * @return the possibly null name of the vertex    */   public String getName() {     return name;   }   /**    * @return the possibly null data of the vertex    */   public T getData() {     return this.data;   }   /**    * @param data    *          The data to set.    */   public void setData(T data) {     this.data = data;   }   /**    * Add an edge to the vertex. If edge.from is this vertex, its an outgoing    * edge. If edge.to is this vertex, its an incoming edge. If neither from or    * to is this vertex, the edge is not added.    *     * @param e -    *          the edge to add    * @return true if the edge was added, false otherwise    */   public boolean addEdge(Edge<T> e) {     if (e.getFrom() == this)       outgoingEdges.add(e);     else if (e.getTo() == this)       incomingEdges.add(e);     else       return false;     return true;   }   /**    * Add an outgoing edge ending at to.    *     * @param to -    *          the destination vertex    * @param cost    *          the edge cost    */   public void addOutgoingEdge(Vertex<T> to, int cost) {     Edge<T> out = new Edge<T>(this, to, cost);     outgoingEdges.add(out);   }   /**    * Add an incoming edge starting at from    *     * @param from -    *          the starting vertex    * @param cost    *          the edge cost    */   public void addIncomingEdge(Vertex<T> from, int cost) {     Edge<T> out = new Edge<T>(this, from, cost);     incomingEdges.add(out);   }   /**    * Check the vertex for either an incoming or outgoing edge mathcing e.    *     * @param e    *          the edge to check    * @return true it has an edge    */   public boolean hasEdge(Edge<T> e) {     if (e.getFrom() == this)       return incomingEdges.contains(e);     else if (e.getTo() == this)       return outgoingEdges.contains(e);     else       return false;   }   /**    * Remove an edge from this vertex    *     * @param e -    *          the edge to remove    * @return true if the edge was removed, false if the edge was not connected    *         to this vertex    */   public boolean remove(Edge<T> e) {     if (e.getFrom() == this)       incomingEdges.remove(e);     else if (e.getTo() == this)       outgoingEdges.remove(e);     else       return false;     return true;   }   /**    *     * @return the count of incoming edges    */   public int getIncomingEdgeCount() {     return incomingEdges.size();   }   /**    * Get the ith incoming edge    *     * @param i    *          the index into incoming edges    * @return ith incoming edge    */   public Edge<T> getIncomingEdge(int i) {     return incomingEdges.get(i);   }   /**    * Get the incoming edges    *     * @return incoming edge list    */   public List getIncomingEdges() {     return this.incomingEdges;   }   /**    *     * @return the count of incoming edges    */   public int getOutgoingEdgeCount() {     return outgoingEdges.size();   }   /**    * Get the ith outgoing edge    *     * @param i    *          the index into outgoing edges    * @return ith outgoing edge    */   public Edge<T> getOutgoingEdge(int i) {     return outgoingEdges.get(i);   }   /**    * Get the outgoing edges    *     * @return outgoing edge list    */   public List getOutgoingEdges() {     return this.outgoingEdges;   }   /**    * Search the outgoing edges looking for an edge whose's edge.to == dest.    *     * @param dest    *          the destination    * @return the outgoing edge going to dest if one exists, null otherwise.    */   public Edge<T> findEdge(Vertex<T> dest) {     for (Edge<T> e : outgoingEdges) {       if (e.getTo() == dest)         return e;     }     return null;   }   /**    * Search the outgoing edges for a match to e.    *     * @param e -    *          the edge to check    * @return e if its a member of the outgoing edges, null otherwise.    */   public Edge<T> findEdge(Edge<T> e) {     if (outgoingEdges.contains(e))       return e;     else       return null;   }   /**    * What is the cost from this vertext to the dest vertex.    *     * @param dest -    *          the destination vertex.    * @return Return Integer.MAX_VALUE if we have no edge to dest, 0 if dest is    *         this vertex, the cost of the outgoing edge otherwise.    */   public int cost(Vertex<T> dest) {     if (dest == this)       return 0;     Edge<T> e = findEdge(dest);     int cost = Integer.MAX_VALUE;     if (e != null)       cost = e.getCost();     return cost;   }   /**    * Is there an outgoing edge ending at dest.    *     * @param dest -    *          the vertex to check    * @return true if there is an outgoing edge ending at vertex, false    *         otherwise.    */   public boolean hasEdge(Vertex<T> dest) {     return (findEdge(dest) != null);   }   /**    * Has this vertex been marked during a visit    *     * @return true is visit has been called    */   public boolean visited() {     return mark;   }   /**    * Set the vertex mark flag.    *     */   public void mark() {     mark = true;   }   /**    * Set the mark state to state.    *     * @param state    *          the state    */   public void setMarkState(int state) {     markState = state;   }   /**    * Get the mark state value.    *     * @return the mark state    */   public int getMarkState() {     return markState;   }   /**    * Visit the vertex and set the mark flag to true.    *     */   public void visit() {     mark();   }   /**    * Clear the visited mark flag.    *     */   public void clearMark() {     mark = false;   }   /**    * @return a string form of the vertex with in and out edges.    */   public String toString() {     StringBuffer tmp = new StringBuffer("Vertex(");     tmp.append(name);     tmp.append(", data=");     tmp.append(data);     tmp.append("), in:[");     for (int i = 0; i < incomingEdges.size(); i++) {       Edge<T> e = incomingEdges.get(i);       if (i > 0)         tmp.append(',');       tmp.append('{');       tmp.append(e.getFrom().name);       tmp.append(',');       tmp.append(e.getCost());       tmp.append('}');     }     tmp.append("], out:[");     for (int i = 0; i < outgoingEdges.size(); i++) {       Edge<T> e = outgoingEdges.get(i);       if (i > 0)         tmp.append(',');       tmp.append('{');       tmp.append(e.getTo().name);       tmp.append(',');       tmp.append(e.getCost());       tmp.append('}');     }     tmp.append(']');     return tmp.toString();   } } /*  * JBoss, Home of Professional Open Source Copyright 2006, Red Hat Middleware  * LLC, and individual contributors by the @authors tag. See the copyright.txt  * in the distribution for a full listing of individual contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is 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 Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * A graph visitor interface.  *   * @author Scott.Stark@jboss.org  * @version $Revision$  * @param <T>  */ interface Visitor<T> {   /**    * Called by the graph traversal methods when a vertex is first visited.    *     * @param g -    *          the graph    * @param v -    *          the vertex being visited.    */   public void visit(Graph<T> g, Vertex<T> v); } /*  * JBoss, Home of Professional Open Source Copyright 2006, Red Hat Middleware  * LLC, and individual contributors by the @authors tag. See the copyright.txt  * in the distribution for a full listing of individual contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is 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 Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * A graph visitor interface that can throw an exception during a visit  * callback.  *   * @author Scott.Stark@jboss.org  * @version $Revision$  * @param <T>  * @param <E>  */ interface VisitorEX<T, E extends Exception> {   /**    * Called by the graph traversal methods when a vertex is first visited.    *     * @param g -    *          the graph    * @param v -    *          the vertex being visited.    * @throws E    *           exception for any error    */   public void visit(Graph<T> g, Vertex<T> v) throws E; } /*  * JBoss, Home of Professional Open Source Copyright 2006, Red Hat Middleware  * LLC, and individual contributors by the @authors tag. See the copyright.txt  * in the distribution for a full listing of individual contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is 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 Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * A spanning tree visitor callback interface  *   * @see Graph#dfsSpanningTree(Vertex, DFSVisitor)  *   * @author Scott.Stark@jboss.org  * @version $Revision$  * @param <T>  */ interface DFSVisitor<T> {   /**    * Called by the graph traversal methods when a vertex is first visited.    *     * @param g -    *          the graph    * @param v -    *          the vertex being visited.    */   public void visit(Graph<T> g, Vertex<T> v);   /**    * Used dfsSpanningTree to notify the visitor of each outgoing edge to an    * unvisited vertex.    *     * @param g -    *          the graph    * @param v -    *          the vertex being visited    * @param e -    *          the outgoing edge from v    */   public void visit(Graph<T> g, Vertex<T> v, Edge<T> e); }