diff --git a/diagrama.png b/diagrama.png index ab18f10..8138db6 100644 Binary files a/diagrama.png and b/diagrama.png differ diff --git a/diagrama.uml b/diagrama.uml index bda85b7..d8ccd5e 100644 --- a/diagrama.uml +++ b/diagrama.uml @@ -3,379 +3,458 @@ JAVA - cl.cromer.estructuras.InsercionController - cl.cromer.estructuras.Grafico.Destacados - cl.cromer.estructuras.ShellController - cl.cromer.estructuras.QuickController - cl.cromer.estructuras.ColaController - cl.cromer.estructuras.Colores - cl.cromer.estructuras.TablaHash - cl.cromer.estructuras.ArbolNodo.Desde - cl.cromer.estructuras.ArbolNodo - cl.cromer.estructuras.Cola - cl.cromer.estructuras.MenuController - cl.cromer.estructuras.ListaEnlazadaCircular - cl.cromer.estructuras.Arbol.PrimerLado - cl.cromer.estructuras.TablaHashController - cl.cromer.estructuras.BurbujaController - cl.cromer.estructuras.Arbol.Tipos - cl.cromer.estructuras.ListaEnlazada.Tipos - cl.cromer.estructuras.ListaEnlazada - cl.cromer.estructuras.SeleccionController - cl.cromer.estructuras.PilaController - cl.cromer.estructuras.Logs - cl.cromer.estructuras.Arbol - cl.cromer.estructuras.Array - cl.cromer.estructuras.Pila - cl.cromer.estructuras.HashItem - cl.cromer.estructuras.ArbolController - cl.cromer.estructuras.Grafico - cl.cromer.estructuras.Array.ParticionarResult - cl.cromer.estructuras.Array.Tipos - cl.cromer.estructuras.TextFieldLimited - cl.cromer.estructuras.ListaEnlazdaController - cl.cromer.estructuras.ArrayController - cl.cromer.estructuras.TextFieldLimited.StyleableProperties - cl.cromer.estructuras.Main + cl.cromer.estructuras.InsercionController + cl.cromer.estructuras.Grafico.Destacados + cl.cromer.estructuras.ShellController + cl.cromer.estructuras.QuickController + cl.cromer.estructuras.GrafoDirigido + cl.cromer.estructuras.ColaController + cl.cromer.estructuras.Colores + cl.cromer.estructuras.VisitorEX + cl.cromer.estructuras.GrafoNoDirigido + cl.cromer.estructuras.TablaHash + cl.cromer.estructuras.ArbolNodo + cl.cromer.estructuras.Cola + cl.cromer.estructuras.MenuController + cl.cromer.estructuras.ListaEnlazadaCircular + cl.cromer.estructuras.Arbol.PrimerLado + cl.cromer.estructuras.TablaHashController + cl.cromer.estructuras.Arbol.Tipos + cl.cromer.estructuras.BurbujaController + cl.cromer.estructuras.DFSVisitor + cl.cromer.estructuras.ListaEnlazada.Tipos + cl.cromer.estructuras.Node + cl.cromer.estructuras.ListaEnlazada + cl.cromer.estructuras.PilaController + cl.cromer.estructuras.SeleccionController + cl.cromer.estructuras.Vertex + cl.cromer.estructuras.Logs + cl.cromer.estructuras.Arbol + cl.cromer.estructuras.Array + cl.cromer.estructuras.GrafoController + cl.cromer.estructuras.Pila + cl.cromer.estructuras.HashItem + cl.cromer.estructuras.ArbolController + cl.cromer.estructuras.Grafico + cl.cromer.estructuras.Array.ParticionarResult + cl.cromer.estructuras.Array.Tipos + cl.cromer.estructuras.TextFieldLimited + cl.cromer.estructuras.Logs.DEBUG_TIPOS + cl.cromer.estructuras.ListaEnlazdaController + cl.cromer.estructuras.ArrayController + cl.cromer.estructuras.Edge + cl.cromer.estructuras.Visitor + cl.cromer.estructuras.TextFieldLimited.StyleableProperties + cl.cromer.estructuras.Main - - - - + + + + - - - + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - - - - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + - - + + - - - - + + + + + + + + + + - - - - - - - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + + + - - - + + + + + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - - - - + + + + + - - - - + + + + - - - - - + + + + + + + - - - - - + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + + + + + + + + + + + + + - - - - + + + + - + Fields diff --git a/src/cl/cromer/estructuras/ArbolController.java b/src/cl/cromer/estructuras/ArbolController.java index da40790..286de35 100644 --- a/src/cl/cromer/estructuras/ArbolController.java +++ b/src/cl/cromer/estructuras/ArbolController.java @@ -178,7 +178,7 @@ public class ArbolController implements Initializable { */ /*private void generarGrafico() { grafico.removerDestacar(); - Node node = contenidoArbol.getChildren().get(0); + GrafoNodo node = contenidoArbol.getChildren().get(0); contenidoArbol.getChildren().clear(); contenidoArbol.getChildren().add(0, node); diff --git a/src/cl/cromer/estructuras/Grafo.java b/src/cl/cromer/estructuras/Grafo.java new file mode 100644 index 0000000..98bc091 --- /dev/null +++ b/src/cl/cromer/estructuras/Grafo.java @@ -0,0 +1,1244 @@ +package cl.cromer.estructuras; + +import java.util.*; + +/** + * Clase de grafos. Se utiliza dos algoritmos para dirigido y no dirigido. + * + * @author Chris Cromer + */ +public class Grafo { + /** + * Esta clase contiene los tipos de grafo. + * + * @author Chris Cromer + */ + final static public class Tipos { + /** + * Tipo de grafo dirigido. + */ + static final public int DIRIGIDO = 0; + + /** + * Tipo de grafo no dirigido. + */ + static final public int NO_DIRIGIDO = 1; + + /** + * El tipo que está elegido. + */ + final private int tipo; + + /** + * Inicilizar el tipo. + * + * @param tipo int: Tipo de grafo, {@value #DIRIGIDO} o {@value #NO_DIRIGIDO} + */ + public Tipos(int tipo) { + switch (tipo) { + case DIRIGIDO: + this.tipo = DIRIGIDO; + break; + case NO_DIRIGIDO: + this.tipo = NO_DIRIGIDO; + break; + default: + this.tipo = NO_DIRIGIDO; + } + } + + /** + * Devolver el tipo. + * + * @return int: El tipo de grafo. + */ + public int getTipo() { + return tipo; + } + } + + /** + * Author: Keith Schwarz (htiek@cs.stanford.edu) + */ + @SuppressWarnings({"unused"}) + static final public class NoDirigido implements Iterable { + /* A map from nodes in the graph to sets of outgoing edges. Each + * set of edges is represented by a map from edges to doubles. + */ + private final Map> mGraph = new HashMap<>(); + + /** + * Adds a new node to the graph. If the node already exists, this + * function is a no-op. + * + * @param node The node to add. + * @return Whether or not the node was added. + */ + public boolean addNode(T node) { + /* If the node already exists, don't do anything. */ + if (mGraph.containsKey(node)) + return false; + + /* Otherwise, add the node with an empty set of outgoing edges. */ + mGraph.put(node, new HashSet<>()); + return true; + } + + /** + * Remove a node from the graph. + * + * @param node The node to remove. + * @return Whether or not the node was removed. + */ + public boolean removeNode(T node) { + /* If the node already exists, don't do anything. */ + if (!mGraph.containsKey(node)) + return false; + + /* Otherwise, remove the node. */ + mGraph.remove(node); + return true; + } + + /** + * Given a node, returns whether that node exists in the graph. + * + * @param node The node in question. + * @return Whether that node eixsts in the graph. + */ + public boolean nodeExists(T node) { + return mGraph.containsKey(node); + } + + /** + * Given two nodes, adds an arc of that length between those nodes. If + * either endpoint does not exist in the graph, throws a + * NoSuchElementException. + * + * @param one The first node. + * @param two The second node. + * @throws NoSuchElementException If either the start or destination nodes + * do not exist. + */ + public void addEdge(T one, T two) { + /* Confirm both endpoints exist. */ + if (!mGraph.containsKey(one) || !mGraph.containsKey(two)) + throw new NoSuchElementException("Both nodes must be in the graph."); + + /* Add the edge in both directions. */ + mGraph.get(one).add(two); + mGraph.get(two).add(one); + } + + /** + * Removes the edge between the indicated endpoints from the graph. If the + * edge does not exist, this operation is a no-op. If either endpoint does + * not exist, this throws a NoSuchElementException. + * + * @param one The start node. + * @param two The destination node. + * @throws NoSuchElementException If either node is not in the graph. + */ + public void removeEdge(T one, T two) { + /* Confirm both endpoints exist. */ + if (!mGraph.containsKey(one) || !mGraph.containsKey(two)) + throw new NoSuchElementException("Both nodes must be in the graph."); + + /* Remove the edges from both adjacency lists. */ + mGraph.get(one).remove(two); + mGraph.get(two).remove(one); + } + + /** + * Given two endpoints, returns whether an edge exists between them. If + * either endpoint does not exist in the graph, throws a + * NoSuchElementException. + * + * @param one The first endpoint. + * @param two The second endpoint. + * @return Whether an edge exists between the endpoints. + * @throws NoSuchElementException If the endpoints are not nodes in the + * graph. + */ + public boolean edgeExists(T one, T two) { + /* Confirm both endpoints exist. */ + if (!mGraph.containsKey(one) || !mGraph.containsKey(two)) + throw new NoSuchElementException("Both nodes must be in the graph."); + + /* Graph is symmetric, so we can just check either endpoint. */ + return mGraph.get(one).contains(two); + } + + /** + * Given a node in the graph, returns an immutable view of the edges + * leaving that node. + * + * @param node The node whose edges should be queried. + * @return An immutable view of the edges leaving that node. + * @throws NoSuchElementException If the node does not exist. + */ + public Set edgesFrom(T node) { + /* Check that the node exists. */ + Set arcs = mGraph.get(node); + if (arcs == null) + throw new NoSuchElementException("Source node does not exist."); + + return Collections.unmodifiableSet(arcs); + } + + /** + * Returns whether a given node is contained in the graph. + * + * @param node The node to test for inclusion. + * @return Whether that node is contained in the graph. + */ + public boolean containsNode(T node) { + return mGraph.containsKey(node); + } + + /** + * Returns an iterator that can traverse the nodes in the graph. + * + * @return An iterator that traverses the nodes in the graph. + */ + public Iterator iterator() { + return mGraph.keySet().iterator(); + } + + /** + * Returns the number of nodes in the graph. + * + * @return The number of nodes in the graph. + */ + public int size() { + return mGraph.size(); + } + + /** + * Returns whether the graph is empty. + * + * @return Whether the graph is empty. + */ + public boolean isEmpty() { + return mGraph.isEmpty(); + } + + /** + * Returns a human-readable representation of the graph. + * + * @return A human-readable representation of the graph. + */ + public String toString() { + return mGraph.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. + */ + @SuppressWarnings({"unchecked", "unused"}) + static final public class Dirigido { + /** 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 of graph verticies */ + private List> verticies; + + /** Vector of edges in the graph */ + private List> edges; + + /** The vertex identified as the root of the graph */ + private Vertex rootVertex; + + /** + * Construct a new graph without any vertices or edges + */ + public Dirigido() { + verticies = new ArrayList<>(); + edges = new ArrayList<>(); + } + + /** + * 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 v) { + boolean added = false; + if (!verticies.contains(v)) { + 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 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 root) { + this.rootVertex = root; + if (!verticies.contains(root)) + 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 getVertex(int n) { + return verticies.get(n); + } + + /** + * Get the graph verticies + * + * @return the graph verticies + */ + public List> getVerticies() { + return this.verticies; + } + + /** + * Insert a directed, weighted Edge into the graph. + * + * @param from - + * the Edge starting vertex + * @param to - + * the Edge ending vertex + * @param cost - + * the Edge weight/cost + * @return true if the Edge was added, false if from already has this Edge + * @throws IllegalArgumentException + * if from/to are not verticies in the graph + */ + public boolean addEdge(Vertex from, Vertex to, int cost) throws IllegalArgumentException { + if (!verticies.contains(from)) + throw new IllegalArgumentException("from is not in graph"); + if (!verticies.contains(to)) + throw new IllegalArgumentException("to is not in graph"); + + Edge e = new Edge<>(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 in the graph + * + * @param from - + * the Edge starting vertex + * @param to - + * the Edge ending vertex + * @param cost - + * the Edge 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 from, Vertex to, int cost) + throws IllegalArgumentException { + return addEdge(from, to, cost) && addEdge(to, from, cost); + } + + /** + * Get the graph edges + * + * @return the graph edges + */ + public List> 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 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 e = v.getOutgoingEdge(n); + v.remove(e); + Vertex to = e.getTo(); + to.remove(e); + edges.remove(e); + } + for (int n = 0; n < v.getIncomingEdgeCount(); n++) { + Edge e = v.getIncomingEdge(n); + v.remove(e); + Vertex predecessor = e.getFrom(); + predecessor.remove(e); + } + return true; + } + + /** + * Remove an Edge from the graph + * + * @param from - + * the Edge starting vertex + * @param to - + * the Edge ending vertex + * @return true if the Edge exists, false otherwise + */ + public boolean removeEdge(Vertex from, Vertex to) { + Edge 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() { + verticies.forEach(Vertex::clearMark); + } + + /** + * Clear the mark state of all edges in the graph by calling clearMark() on + * all edges. + */ + public void clearEdges() { + edges.forEach(Edge::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(Dirigido, Vertex) + */ + public void depthFirstSearch(Vertex v, final Visitor visitor) { + VisitorEX wrapper = (g, v1) -> { + if (visitor != null) + visitor.visit(g, v1); + }; + this.depthFirstSearch(v, wrapper); + } + + /** + * Perform a depth first serach using recursion. The search may be cut short + * if the visitor throws an exception. + * + * @param - + * exception + * @param v - + * the Vertex to start the search from + * @param visitor - + * the vistor to inform prior to + * @see Visitor#visit(Dirigido, Vertex) + * @throws E + * if visitor.visit throws an exception + */ + public void depthFirstSearch(Vertex v, VisitorEX visitor) throws E { + if (visitor != null) + visitor.visit(this, v); + v.visit(); + for (int i = 0; i < v.getOutgoingEdgeCount(); i++) { + Edge 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 v, final Visitor visitor) { + VisitorEX wrapper = (g, v1) -> { + if (visitor != null) + visitor.visit(g, v1); + }; + 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 - + * exception + * @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 void breadthFirstSearch(Vertex v, VisitorEX visitor) + throws E { + LinkedList> q = new LinkedList<>(); + + q.add(v); + if (visitor != null) + visitor.visit(this, v); + v.visit(); + while (!q.isEmpty()) { + v = q.removeFirst(); + for (int i = 0; i < v.getOutgoingEdgeCount(); i++) { + Edge e = v.getOutgoingEdge(i); + Vertex 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 v, DFSVisitor visitor) { + v.visit(); + if (visitor != null) + visitor.visit(this, v); + + for (int i = 0; i < v.getOutgoingEdgeCount(); i++) { + Edge 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 findVertexByName(String name) { + Vertex match = null; + for (Vertex 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 findVertexByData(T data, Comparator compare) { + Vertex match = null; + for (Vertex 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[] findCycles() { + ArrayList> cycleEdges = new ArrayList<>(); + // Mark all verticies as white + for (int n = 0; n < verticies.size(); n++) { + Vertex v = getVertex(n); + v.setMarkState(VISIT_COLOR_WHITE); + } + for (int n = 0; n < verticies.size(); n++) { + Vertex v = getVertex(n); + visit(v, cycleEdges); + } + + Edge[] cycles = new Edge[cycleEdges.size()]; + cycleEdges.toArray(cycles); + return cycles; + } + + private void visit(Vertex v, ArrayList> cycleEdges) { + v.setMarkState(VISIT_COLOR_GREY); + int count = v.getOutgoingEdgeCount(); + for (int n = 0; n < count; n++) { + Edge e = v.getOutgoingEdge(n); + Vertex u = e.getTo(); + if (u.getMarkState() == VISIT_COLOR_GREY) { + // A cycle Edge + cycleEdges.add(e); + } else if (u.getMarkState() == VISIT_COLOR_WHITE) { + visit(u, cycleEdges); + } + } + v.setMarkState(VISIT_COLOR_BLACK); + } + + public String toString() { + StringBuilder tmp = new StringBuilder("Dirigido["); + verticies.forEach(tmp::append); + tmp.append(']'); + return tmp.toString(); + } + + } + + /** + * A directed, weighted edge in a graph + * + * @author Scott.Stark@jboss.org + * @version $Revision$ + * @param + */ + @SuppressWarnings("unused") + static final public class Edge { + private Vertex from; + + private Vertex 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 from, Vertex 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 from, Vertex to, int cost) { + this.from = from; + this.to = to; + this.cost = cost; + mark = false; + } + + /** + * Get the ending vertex + * + * @return ending vertex + */ + public Vertex getTo() { + return to; + } + + /** + * Get the starting vertex + * + * @return starting vertex + */ + public Vertex 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() { + return "Edge[from: " + from.getName() + + ",to: " + + to.getName() + + ", cost: " + + cost + + "]"; + } + } + + /** + * A named graph vertex with optional data. + * + * @author Scott.Stark@jboss.org + * @version $Revision$ + * @param + */ + @SuppressWarnings({"unchecked", "unused"}) + static final public class Vertex { + private List> incomingEdges; + + private List> 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 - + * return 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<>(); + outgoingEdges = new ArrayList<>(); + 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 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 to, int cost) { + Edge out = new Edge<>(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 from, int cost) { + Edge out = new Edge<>(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 e) { + if (e.getFrom() == this) { + return incomingEdges.contains(e); + } + else { + return e.getTo() == this && outgoingEdges.contains(e); + } + } + + /** + * 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 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 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 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 findEdge(Vertex dest) { + for (Edge 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 findEdge(Edge 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 dest) { + if (dest == this) + return 0; + + Edge 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 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() { + StringBuilder tmp = new StringBuilder("Vertex("); + tmp.append(name); + tmp.append(", data="); + tmp.append(data); + tmp.append("), in:["); + for (int i = 0; i < incomingEdges.size(); i++) { + Edge 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 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(); + } + } + + /** + * A graph visitor interface. + * + * @author Scott.Stark@jboss.org + * @version $Revision$ + * @param + */ + public interface Visitor { + /** + * Called by the graph traversal methods when a vertex is first visited. + * + * @param g - + * the graph + * @param v - + * the vertex being visited. + */ + void visit(Dirigido g, Vertex v); + } + + /** + * A graph visitor interface that can throw an exception during a visit + * callback. + * + * @author Scott.Stark@jboss.org + * @version $Revision$ + * @param + * @param + */ + public interface VisitorEX { + /** + * 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 + */ + void visit(Dirigido g, Vertex v) throws E; + } + + /** + * A spanning tree visitor callback interface + * + * @see Dirigido#dfsSpanningTree(Vertex, DFSVisitor) + * + * @author Scott.Stark@jboss.org + * @version $Revision$ + * @param + */ + public interface DFSVisitor { + /** + * Called by the graph traversal methods when a vertex is first visited. + * + * @param g - + * the graph + * @param v - + * the vertex being visited. + */ + void visit(Dirigido g, Vertex 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 + */ + void visit(Dirigido g, Vertex v, Edge e); + } +} \ No newline at end of file diff --git a/src/cl/cromer/estructuras/GrafoController.java b/src/cl/cromer/estructuras/GrafoController.java index d511fda..69ef68b 100644 --- a/src/cl/cromer/estructuras/GrafoController.java +++ b/src/cl/cromer/estructuras/GrafoController.java @@ -9,6 +9,7 @@ import javafx.scene.shape.ArcType; import javafx.scene.text.Text; import java.net.URL; +import java.util.List; import java.util.Random; import java.util.ResourceBundle; @@ -59,9 +60,19 @@ public class GrafoController implements Initializable { private ResourceBundle resourceBundle; /** - * El arbol usado en la aplicación. + * Tipo de grafo. */ - private GrafoNoDirigido grafoNoDirigido; + private Grafo.Tipos grafoTipos; + + /** + * El grafo dirigido usado en la aplicación. + */ + private Grafo.Dirigido dirigido; + + /** + * El grafo no dirigido usado en la aplicación. + */ + private Grafo.NoDirigido noDirigido; /** * Grafico rectangulos. @@ -71,7 +82,12 @@ public class GrafoController implements Initializable { /** * Nodos. */ - private Node[] nodes; + private GrafoNodo[] grafoNodos; + + /** + * A static weight. + */ + final static private int WEIGHT = 0; /** * Inicializar todos los datos y dibujar las graficas. @@ -83,7 +99,7 @@ public class GrafoController implements Initializable { public void initialize(URL location, ResourceBundle resourceBundle) { this.resourceBundle = resourceBundle; - grafoNoDirigido = null; + noDirigido = null; scene = null; } @@ -93,30 +109,53 @@ public class GrafoController implements Initializable { initializeGrafo(); } + Random random = new Random(); + int maximo = 99; + int minimo = 0; + int rango = maximo - minimo + 1; + Array array = new Array(5); for (int i = 0; i < 5; i++) { - if (nodes[i] != null) { - array.insertar(nodes[i].getValue()); + if (grafoNodos[i] != null) { + array.insertar(grafoNodos[i].getValue()); } } - for (int i = 0; i < 5; i++) { - if (nodes[i] == null) { - Random random = new Random(); - int maximo = 99; - int minimo = 0; - int rango = maximo - minimo + 1; + if (grafoTipos.getTipo() == Grafo.Tipos.NO_DIRIGIDO) { + for (int i = 0; i < 5; i++) { + if (grafoNodos[i] == null) { - int numero = random.nextInt(rango) + minimo; - // Check if value is in array - while (array.buscar(numero) != -1) { - numero = random.nextInt(rango) + minimo; + int numero = random.nextInt(rango) + minimo; + // Check if value is in array + while (array.buscar(numero) != - 1) { + numero = random.nextInt(rango) + minimo; + } + + grafoNodos[i] = new GrafoNodo(numero); + + noDirigido.addNode(grafoNodos[i]); } - - nodes[i] = new Node(numero); - grafoNoDirigido.addNode(nodes[i]); } } + else { + for (int i = 0; i < 5; i++) { + if (grafoNodos[i] == null) { + + int numero = random.nextInt(rango) + minimo; + // Check if value is in array + while (array.buscar(numero) != - 1) { + numero = random.nextInt(rango) + minimo; + } + + grafoNodos[i] = new GrafoNodo(numero); + + Grafo.Vertex vertex = new Grafo.Vertex<>("test"); + vertex.setData(grafoNodos[i]); + dirigido.addVertex(vertex); + } + } + } + generarGrafico(); } @@ -126,8 +165,8 @@ public class GrafoController implements Initializable { initializeGrafo(); } - this.grafoNoDirigido = new GrafoNoDirigido<>(); - this.nodes = new Node[5]; + this.noDirigido = new Grafo.NoDirigido<>(); + this.grafoNodos = new GrafoNodo[5]; generarGrafico(); } @@ -148,11 +187,11 @@ public class GrafoController implements Initializable { try { int i; for (i = 0; i < 5; i++) { - if (nodes[i] == null) { - nodes[i] = new Node(Integer.valueOf(valorGrafo.getText())); + if (grafoNodos[i] == null) { + grafoNodos[i] = new GrafoNodo(Integer.valueOf(valorGrafo.getText())); break; } - else if (nodes[i].getValue() == Integer.valueOf(valorGrafo.getText())) { + else if (grafoNodos[i].getValue() == Integer.valueOf(valorGrafo.getText())) { Main.mostrarError(resourceBundle.getString("grafoNodoExiste"), resourceBundle); i = -1; break; @@ -164,7 +203,7 @@ public class GrafoController implements Initializable { Main.mostrarError(resourceBundle.getString("grafoLleno"), resourceBundle); } else if (i != -1) { - boolean exito = grafoNoDirigido.addNode(nodes[i]); + boolean exito = noDirigido.addNode(grafoNodos[i]); if (exito) { valorGrafo.setText(""); generarGrafico(); @@ -201,15 +240,15 @@ public class GrafoController implements Initializable { try { int i; for (i = 0; i < 5; i++) { - if (nodes[i] != null && nodes[i].getValue() == Integer.valueOf(valorGrafo.getText())) { + if (grafoNodos[i] != null && grafoNodos[i].getValue() == Integer.valueOf(valorGrafo.getText())) { break; } } if (i != 5) { - boolean exito = grafoNoDirigido.removeNode(nodes[i]); + boolean exito = noDirigido.removeNode(grafoNodos[i]); if (exito) { - nodes[i] = null; + grafoNodos[i] = null; valorGrafo.setText(""); generarGrafico(); } @@ -241,16 +280,16 @@ public class GrafoController implements Initializable { } if (valorNodo1.getText() != null && ! valorNodo1.getText().trim().equals("") && valorNodo2.getText() != null && ! valorNodo2.getText().trim().equals("")) { - Node[] nodos = getNodosEdge(); + GrafoNodo[] nodos = getNodosEdge(); - if (nodos[0] == null || nodos[1] == null || !grafoNoDirigido.nodeExists(nodos[0]) || !grafoNoDirigido.nodeExists(nodos[1])) { + if (nodos[0] == null || nodos[1] == null || ! noDirigido.nodeExists(nodos[0]) || ! noDirigido.nodeExists(nodos[1])) { Main.mostrarError(resourceBundle.getString("grafoNoNodo"), resourceBundle); } - else if (grafoNoDirigido.edgeExists(nodos[0], nodos[1])) { + else if (noDirigido.edgeExists(nodos[0], nodos[1])) { Main.mostrarError(resourceBundle.getString("grafoEdgeExiste"), resourceBundle); } else { - grafoNoDirigido.addEdge(nodos[0], nodos[1]); + noDirigido.addEdge(nodos[0], nodos[1]); } } else { @@ -270,16 +309,16 @@ public class GrafoController implements Initializable { } if (valorNodo1.getText() != null && ! valorNodo1.getText().trim().equals("") && valorNodo2.getText() != null && ! valorNodo2.getText().trim().equals("")) { - Node[] nodos = getNodosEdge(); + GrafoNodo[] nodos = getNodosEdge(); - if (nodos[0] == null || nodos[1] == null || !grafoNoDirigido.nodeExists(nodos[0]) || !grafoNoDirigido.nodeExists(nodos[1])) { + if (nodos[0] == null || nodos[1] == null || ! noDirigido.nodeExists(nodos[0]) || ! noDirigido.nodeExists(nodos[1])) { Main.mostrarError(resourceBundle.getString("grafoNoNodo"), resourceBundle); } - else if (!grafoNoDirigido.edgeExists(nodos[0], nodos[1])) { + else if (! noDirigido.edgeExists(nodos[0], nodos[1])) { Main.mostrarError(resourceBundle.getString("grafoNoEdge"), resourceBundle); } else { - grafoNoDirigido.removeEdge(nodos[0], nodos[1]); + noDirigido.removeEdge(nodos[0], nodos[1]); } } else { @@ -295,24 +334,31 @@ public class GrafoController implements Initializable { private void initializeGrafo() { scene = contenidoGrafo.getScene(); grafico = new Grafico(scene); - this.grafoNoDirigido = new GrafoNoDirigido<>(); - this.nodes = new Node[5]; + grafoTipos = (Grafo.Tipos) scene.getUserData(); + grafoNodos = new GrafoNodo[5]; + + if (grafoTipos.getTipo() == Grafo.Tipos.NO_DIRIGIDO) { + noDirigido = new Grafo.NoDirigido<>(); + } + else { + dirigido = new Grafo.Dirigido<>(); + } } /** * Devolver los nodos que existen. * - * @return Node[]: Los nodos que se busca. + * @return GrafoNodo[]: Los nodos que se busca. */ - private Node[] getNodosEdge() { - Node[] nodos = new Node[2]; + private GrafoNodo[] getNodosEdge() { + GrafoNodo[] nodos = new GrafoNodo[2]; for (int i = 0; i < 5; i++) { - if (nodes[i] != null) { - if (Integer.valueOf(valorNodo1.getText()) == nodes[i].getValue()) { - nodos[0] = nodes[i]; + if (grafoNodos[i] != null) { + if (Integer.valueOf(valorNodo1.getText()) == grafoNodos[i].getValue()) { + nodos[0] = grafoNodos[i]; } - if (Integer.valueOf(valorNodo2.getText()) == nodes[i].getValue()) { - nodos[1] = nodes[i]; + if (Integer.valueOf(valorNodo2.getText()) == grafoNodos[i].getValue()) { + nodos[1] = grafoNodos[i]; } if (nodos[0] != null && nodos[1] != null) { break; @@ -333,7 +379,7 @@ public class GrafoController implements Initializable { GraphicsContext graphicsContext = contenidoGrafo.getGraphicsContext2D(); graphicsContext.clearRect(0, 0, contenidoGrafo.getWidth(), contenidoGrafo.getHeight()); - if (nodes[0] != null) { + if (grafoNodos[0] != null) { graphicsContext.setFill(colores.getFondo()); graphicsContext.setStroke(colores.getBorder()); @@ -341,12 +387,12 @@ public class GrafoController implements Initializable { graphicsContext.strokeOval(10, 10, 40, 40); graphicsContext.setFill(colores.getTexto()); - int x = textX(25, String.valueOf(nodes[0].getValue())); - graphicsContext.fillText(String.valueOf(nodes[0].getValue()), x, 35); + int x = textX(25, String.valueOf(grafoNodos[0].getValue())); + graphicsContext.fillText(String.valueOf(grafoNodos[0].getValue()), x, 35); } colores.siguinteColor(); - if (nodes[1] != null) { + if (grafoNodos[1] != null) { graphicsContext.setFill(colores.getFondo()); graphicsContext.setStroke(colores.getBorder()); @@ -354,12 +400,12 @@ public class GrafoController implements Initializable { graphicsContext.strokeOval(210, 10, 40, 40); graphicsContext.setStroke(colores.getTexto()); - int x = textX(225, String.valueOf(nodes[1].getValue())); - graphicsContext.strokeText(String.valueOf(nodes[1].getValue()), x, 35); + int x = textX(225, String.valueOf(grafoNodos[1].getValue())); + graphicsContext.strokeText(String.valueOf(grafoNodos[1].getValue()), x, 35); } colores.siguinteColor(); - if (nodes[2] != null) { + if (grafoNodos[2] != null) { graphicsContext.setFill(colores.getFondo()); graphicsContext.setStroke(colores.getBorder()); @@ -367,12 +413,12 @@ public class GrafoController implements Initializable { graphicsContext.strokeOval(10, 210, 40, 40); graphicsContext.setStroke(colores.getTexto()); - int x = textX(25, String.valueOf(nodes[2].getValue())); - graphicsContext.strokeText(String.valueOf(nodes[2].getValue()), x, 235); + int x = textX(25, String.valueOf(grafoNodos[2].getValue())); + graphicsContext.strokeText(String.valueOf(grafoNodos[2].getValue()), x, 235); } colores.siguinteColor(); - if (nodes[3] != null) { + if (grafoNodos[3] != null) { graphicsContext.setFill(colores.getFondo()); graphicsContext.setStroke(colores.getBorder()); @@ -380,12 +426,12 @@ public class GrafoController implements Initializable { graphicsContext.strokeOval(210, 210, 40, 40); graphicsContext.setStroke(colores.getTexto()); - int x = textX(225, String.valueOf(nodes[3].getValue())); - graphicsContext.strokeText(String.valueOf(nodes[3].getValue()), x, 235); + int x = textX(225, String.valueOf(grafoNodos[3].getValue())); + graphicsContext.strokeText(String.valueOf(grafoNodos[3].getValue()), x, 235); } colores.siguinteColor(); - if (nodes[4] != null) { + if (grafoNodos[4] != null) { graphicsContext.setFill(colores.getFondo()); graphicsContext.setStroke(colores.getBorder()); @@ -393,74 +439,91 @@ public class GrafoController implements Initializable { graphicsContext.strokeOval(105, 410, 40, 40); graphicsContext.setStroke(colores.getTexto()); - int x = textX(120, String.valueOf(nodes[4].getValue())); - graphicsContext.strokeText(String.valueOf(nodes[4].getValue()), x, 435); + int x = textX(120, String.valueOf(grafoNodos[4].getValue())); + graphicsContext.strokeText(String.valueOf(grafoNodos[4].getValue()), x, 435); } graphicsContext.setStroke(colores.getBorder()); + if (grafoTipos.getTipo() == Grafo.Tipos.NO_DIRIGIDO) { + // Line between 0 and 0. + if (grafoNodos[0] != null && noDirigido.edgeExists(grafoNodos[0], grafoNodos[0])) { + graphicsContext.strokeArc(15, 40, 29, 30, 145, 250, ArcType.OPEN); + } + // Line between 1 and 1. + if (grafoNodos[1] != null && noDirigido.edgeExists(grafoNodos[1], grafoNodos[1])) { + graphicsContext.strokeArc(215, 40, 29, 30, 145, 250, ArcType.OPEN); + } + // Line between 2 and 2. + if (grafoNodos[2] != null && noDirigido.edgeExists(grafoNodos[2], grafoNodos[2])) { + graphicsContext.strokeArc(15, 240, 29, 30, 145, 250, ArcType.OPEN); + } + // Line between 3 and 3. + if (grafoNodos[3] != null && noDirigido.edgeExists(grafoNodos[3], grafoNodos[3])) { + graphicsContext.strokeArc(215, 240, 29, 30, 145, 250, ArcType.OPEN); + } + // Line between 4 and 4. + if (grafoNodos[4] != null && noDirigido.edgeExists(grafoNodos[4], grafoNodos[4])) { + graphicsContext.strokeArc(110, 440, 29, 30, 145, 250, ArcType.OPEN); + } + // Line between 0 and 1. + if (grafoNodos[0] != null && grafoNodos[1] != null && noDirigido.edgeExists(grafoNodos[0], grafoNodos[1])) { + graphicsContext.strokeLine(50, 30, 210, 30); + } + // Line between 0 and 2. + if (grafoNodos[0] != null && grafoNodos[2] != null && noDirigido.edgeExists(grafoNodos[0], grafoNodos[2])) { + graphicsContext.strokeLine(30, 50, 30, 210); + } + // Line between 0 and 3. + if (grafoNodos[0] != null && grafoNodos[3] != null && noDirigido.edgeExists(grafoNodos[0], grafoNodos[3])) { + graphicsContext.strokeLine(45, 45, 215, 215); + } + // Line between 0 and 4. + if (grafoNodos[0] != null && grafoNodos[4] != null && noDirigido.edgeExists(grafoNodos[0], grafoNodos[4])) { + graphicsContext.strokeLine(38, 50, 125, 410); + } + // Line between 1 and 2. + if (grafoNodos[1] != null && grafoNodos[2] != null && noDirigido.edgeExists(grafoNodos[1], grafoNodos[2])) { + graphicsContext.strokeLine(45, 215, 215, 45); + } + // Line between 1 and 3. + if (grafoNodos[1] != null && grafoNodos[3] != null && noDirigido.edgeExists(grafoNodos[1], grafoNodos[3])) { + graphicsContext.strokeLine(230, 50, 230, 210); + } + // Line between 1 and 4. + if (grafoNodos[1] != null && grafoNodos[4] != null && noDirigido.edgeExists(grafoNodos[1], grafoNodos[4])) { + graphicsContext.strokeLine(221, 50, 125, 410); + } + // Line between 2 and 3 + if (grafoNodos[2] != null && grafoNodos[3] != null && noDirigido.edgeExists(grafoNodos[2], grafoNodos[3])) { + graphicsContext.strokeLine(50, 230, 210, 230); + } + // Line between 2 and 4. + if (grafoNodos[2] != null && grafoNodos[4] != null && noDirigido.edgeExists(grafoNodos[2], grafoNodos[4])) { + graphicsContext.strokeLine(38, 250, 125, 410); + } + // Line between 3 and 4. + if (grafoNodos[3] != null && grafoNodos[4] != null && noDirigido.edgeExists(grafoNodos[3], grafoNodos[4])) { + graphicsContext.strokeLine(221, 250, 125, 410); + } + } + else { + Grafo.Vertex vertex = dirigido.getVertex(0); + dirigido.addEdge(vertex, vertex, WEIGHT); + List> edges = dirigido.getEdges(); + for (Grafo.Edge edge : edges) { + Grafo.Vertex vFrom = edge.getFrom(); + Grafo.Vertex vTo = edge.getTo(); + GrafoNodo from = (GrafoNodo) vFrom.getData(); + GrafoNodo to = (GrafoNodo) vTo.getData(); - // Line between 0 and 0. - if (nodes[0] != null && grafoNoDirigido.edgeExists(nodes[0], nodes[0])) { - graphicsContext.strokeArc(15, 40, 29, 30, 145, 250, ArcType.OPEN); - } - // Line between 1 and 1. - if (nodes[1] != null && grafoNoDirigido.edgeExists(nodes[1], nodes[1])) { - graphicsContext.strokeArc(215, 40, 29, 30, 145, 250, ArcType.OPEN); - } - // Line between 2 and 2. - if (nodes[2] != null && grafoNoDirigido.edgeExists(nodes[2], nodes[2])) { - graphicsContext.strokeArc(15, 240, 29, 30, 145, 250, ArcType.OPEN); - } - // Line between 3 and 3. - if (nodes[3] != null && grafoNoDirigido.edgeExists(nodes[3], nodes[3])) { - graphicsContext.strokeArc(215, 240, 29, 30, 145, 250, ArcType.OPEN); - } - // Line between 4 and 4. - if (nodes[4] != null && grafoNoDirigido.edgeExists(nodes[4], nodes[4])) { - graphicsContext.strokeArc(110, 440, 29, 30, 145, 250, ArcType.OPEN); - } - - // Line between 0 and 1. - if (nodes[0] != null && nodes[1] != null && grafoNoDirigido.edgeExists(nodes[0], nodes[1])) { - graphicsContext.strokeLine(50, 30, 210, 30); - } - // Line between 0 and 2. - if (nodes[0] != null && nodes[2] != null && grafoNoDirigido.edgeExists(nodes[0], nodes[2])) { - graphicsContext.strokeLine(30, 50, 30, 210); - } - // Line between 0 and 3. - if (nodes[0] != null && nodes[3] != null && grafoNoDirigido.edgeExists(nodes[0], nodes[3])) { - graphicsContext.strokeLine(45, 45, 215, 215); - } - // Line between 0 and 4. - if (nodes[0] != null && nodes[4] != null && grafoNoDirigido.edgeExists(nodes[0], nodes[4])) { - graphicsContext.strokeLine(38, 50, 125, 410); - } - // Line between 1 and 2. - if (nodes[1] != null && nodes[2] != null && grafoNoDirigido.edgeExists(nodes[1], nodes[2])) { - graphicsContext.strokeLine(45, 215, 215, 45); - } - // Line between 1 and 3. - if (nodes[1] != null && nodes[3] != null && grafoNoDirigido.edgeExists(nodes[1], nodes[3])) { - graphicsContext.strokeLine(230, 50, 230, 210); - } - // Line between 1 and 4. - if (nodes[1] != null && nodes[4] != null && grafoNoDirigido.edgeExists(nodes[1], nodes[4])) { - graphicsContext.strokeLine(221, 50, 125, 410); - } - // Line between 2 and 3 - if (nodes[2] != null && nodes[3] != null && grafoNoDirigido.edgeExists(nodes[2], nodes[3])) { - graphicsContext.strokeLine(50, 230, 210, 230); - } - // Line between 2 and 4. - if (nodes[2] != null && nodes[4] != null && grafoNoDirigido.edgeExists(nodes[2], nodes[4])) { - graphicsContext.strokeLine(38, 250, 125, 410); - } - // Line between 3 and 4. - if (nodes[3] != null && nodes[4] != null && grafoNoDirigido.edgeExists(nodes[3], nodes[4])) { - graphicsContext.strokeLine(221, 250, 125, 410); + if (from == grafoNodos[0]) { + if (to == from) { + graphicsContext.strokeArc(15, 40, 29, 30, 145, 250, ArcType.OPEN); + } + } + } } } diff --git a/src/cl/cromer/estructuras/GrafoDirigido.java b/src/cl/cromer/estructuras/GrafoDirigido.java deleted file mode 100644 index da3ce48..0000000 --- a/src/cl/cromer/estructuras/GrafoDirigido.java +++ /dev/null @@ -1,1016 +0,0 @@ -package cl.cromer.estructuras; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; - -/* - * 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. - */ - -@SuppressWarnings({"unchecked", "unused"}) -public class GrafoDirigido { - /** 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 of graph verticies */ - private List> verticies; - - /** Vector of edges in the graph */ - private List> edges; - - /** The vertex identified as the root of the graph */ - private Vertex rootVertex; - - /** - * Construct a new graph without any vertices or edges - */ - public GrafoDirigido() { - verticies = new ArrayList<>(); - edges = new ArrayList<>(); - } - - /** - * 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 v) { - boolean added = false; - if (!verticies.contains(v)) { - 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 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 root) { - this.rootVertex = root; - if (!verticies.contains(root)) - 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 getVertex(int n) { - return verticies.get(n); - } - - /** - * Get the graph verticies - * - * @return the graph verticies - */ - public List> getVerticies() { - return this.verticies; - } - - /** - * Insert a directed, weighted Edge into the graph. - * - * @param from - - * the Edge starting vertex - * @param to - - * the Edge ending vertex - * @param cost - - * the Edge weight/cost - * @return true if the Edge was added, false if from already has this Edge - * @throws IllegalArgumentException - * if from/to are not verticies in the graph - */ - public boolean addEdge(Vertex from, Vertex to, int cost) throws IllegalArgumentException { - if (!verticies.contains(from)) - throw new IllegalArgumentException("from is not in graph"); - if (!verticies.contains(to)) - throw new IllegalArgumentException("to is not in graph"); - - Edge e = new Edge<>(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 in the graph - * - * @param from - - * the Edge starting vertex - * @param to - - * the Edge ending vertex - * @param cost - - * the Edge 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 from, Vertex to, int cost) - throws IllegalArgumentException { - return addEdge(from, to, cost) && addEdge(to, from, cost); - } - - /** - * Get the graph edges - * - * @return the graph edges - */ - public List> 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 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 e = v.getOutgoingEdge(n); - v.remove(e); - Vertex to = e.getTo(); - to.remove(e); - edges.remove(e); - } - for (int n = 0; n < v.getIncomingEdgeCount(); n++) { - Edge e = v.getIncomingEdge(n); - v.remove(e); - Vertex predecessor = e.getFrom(); - predecessor.remove(e); - } - return true; - } - - /** - * Remove an Edge from the graph - * - * @param from - - * the Edge starting vertex - * @param to - - * the Edge ending vertex - * @return true if the Edge exists, false otherwise - */ - public boolean removeEdge(Vertex from, Vertex to) { - Edge 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() { - verticies.forEach(Vertex::clearMark); - } - - /** - * Clear the mark state of all edges in the graph by calling clearMark() on - * all edges. - */ - public void clearEdges() { - edges.forEach(Edge::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(GrafoDirigido, Vertex) - */ - public void depthFirstSearch(Vertex v, final Visitor visitor) { - VisitorEX wrapper = (g, v1) -> { - if (visitor != null) - visitor.visit(g, v1); - }; - this.depthFirstSearch(v, wrapper); - } - - /** - * Perform a depth first serach using recursion. The search may be cut short - * if the visitor throws an exception. - * - * @param - - * exception - * @param v - - * the Vertex to start the search from - * @param visitor - - * the vistor to inform prior to - * @see Visitor#visit(GrafoDirigido, Vertex) - * @throws E - * if visitor.visit throws an exception - */ - public void depthFirstSearch(Vertex v, VisitorEX visitor) throws E { - if (visitor != null) - visitor.visit(this, v); - v.visit(); - for (int i = 0; i < v.getOutgoingEdgeCount(); i++) { - Edge 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 v, final Visitor visitor) { - VisitorEX wrapper = (g, v1) -> { - if (visitor != null) - visitor.visit(g, v1); - }; - 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 - - * exception - * @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 void breadthFirstSearch(Vertex v, VisitorEX visitor) - throws E { - LinkedList> q = new LinkedList<>(); - - q.add(v); - if (visitor != null) - visitor.visit(this, v); - v.visit(); - while (!q.isEmpty()) { - v = q.removeFirst(); - for (int i = 0; i < v.getOutgoingEdgeCount(); i++) { - Edge e = v.getOutgoingEdge(i); - Vertex 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 v, DFSVisitor visitor) { - v.visit(); - if (visitor != null) - visitor.visit(this, v); - - for (int i = 0; i < v.getOutgoingEdgeCount(); i++) { - Edge 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 findVertexByName(String name) { - Vertex match = null; - for (Vertex 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 findVertexByData(T data, Comparator compare) { - Vertex match = null; - for (Vertex 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[] findCycles() { - ArrayList> cycleEdges = new ArrayList<>(); - // Mark all verticies as white - for (int n = 0; n < verticies.size(); n++) { - Vertex v = getVertex(n); - v.setMarkState(VISIT_COLOR_WHITE); - } - for (int n = 0; n < verticies.size(); n++) { - Vertex v = getVertex(n); - visit(v, cycleEdges); - } - - Edge[] cycles = new Edge[cycleEdges.size()]; - cycleEdges.toArray(cycles); - return cycles; - } - - private void visit(Vertex v, ArrayList> cycleEdges) { - v.setMarkState(VISIT_COLOR_GREY); - int count = v.getOutgoingEdgeCount(); - for (int n = 0; n < count; n++) { - Edge e = v.getOutgoingEdge(n); - Vertex u = e.getTo(); - if (u.getMarkState() == VISIT_COLOR_GREY) { - // A cycle Edge - cycleEdges.add(e); - } else if (u.getMarkState() == VISIT_COLOR_WHITE) { - visit(u, cycleEdges); - } - } - v.setMarkState(VISIT_COLOR_BLACK); - } - - public String toString() { - StringBuilder tmp = new StringBuilder("GrafoDirigido["); - verticies.forEach(tmp::append); - tmp.append(']'); - return tmp.toString(); - } - -} - -/** - * A directed, weighted edge in a graph - * - * @author Scott.Stark@jboss.org - * @version $Revision$ - * @param - */ -@SuppressWarnings("unused") -class Edge { - private Vertex from; - - private Vertex 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 from, Vertex 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 from, Vertex to, int cost) { - this.from = from; - this.to = to; - this.cost = cost; - mark = false; - } - - /** - * Get the ending vertex - * - * @return ending vertex - */ - public Vertex getTo() { - return to; - } - - /** - * Get the starting vertex - * - * @return starting vertex - */ - public Vertex 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() { - return "Edge[from: " + from.getName() + - ",to: " + - to.getName() + - ", cost: " + - cost + - "]"; - } -} - -/** - * A named graph vertex with optional data. - * - * @author Scott.Stark@jboss.org - * @version $Revision$ - * @param - */ -@SuppressWarnings({"unchecked", "unused"}) -class Vertex { - private List> incomingEdges; - - private List> 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 - - * return 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<>(); - outgoingEdges = new ArrayList<>(); - 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 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 to, int cost) { - Edge out = new Edge<>(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 from, int cost) { - Edge out = new Edge<>(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 e) { - if (e.getFrom() == this) { - return incomingEdges.contains(e); - } - else { - return e.getTo() == this && outgoingEdges.contains(e); - } - } - - /** - * 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 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 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 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 findEdge(Vertex dest) { - for (Edge 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 findEdge(Edge 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 dest) { - if (dest == this) - return 0; - - Edge 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 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() { - StringBuilder tmp = new StringBuilder("Vertex("); - tmp.append(name); - tmp.append(", data="); - tmp.append(data); - tmp.append("), in:["); - for (int i = 0; i < incomingEdges.size(); i++) { - Edge 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 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(); - } -} - -/** - * A graph visitor interface. - * - * @author Scott.Stark@jboss.org - * @version $Revision$ - * @param - */ -interface Visitor { - /** - * Called by the graph traversal methods when a vertex is first visited. - * - * @param g - - * the graph - * @param v - - * the vertex being visited. - */ - void visit(GrafoDirigido g, Vertex v); -} - -/** - * A graph visitor interface that can throw an exception during a visit - * callback. - * - * @author Scott.Stark@jboss.org - * @version $Revision$ - * @param - * @param - */ -interface VisitorEX { - /** - * 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 - */ - void visit(GrafoDirigido g, Vertex v) throws E; -} - -/** - * A spanning tree visitor callback interface - * - * @see GrafoDirigido#dfsSpanningTree(Vertex, DFSVisitor) - * - * @author Scott.Stark@jboss.org - * @version $Revision$ - * @param - */ -interface DFSVisitor { - /** - * Called by the graph traversal methods when a vertex is first visited. - * - * @param g - - * the graph - * @param v - - * the vertex being visited. - */ - void visit(GrafoDirigido g, Vertex 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 - */ - void visit(GrafoDirigido g, Vertex v, Edge e); -} \ No newline at end of file diff --git a/src/cl/cromer/estructuras/GrafoNoDirigido.java b/src/cl/cromer/estructuras/GrafoNoDirigido.java deleted file mode 100644 index f522738..0000000 --- a/src/cl/cromer/estructuras/GrafoNoDirigido.java +++ /dev/null @@ -1,203 +0,0 @@ -package cl.cromer.estructuras; - -import java.util.*; - -/***************************************************************************** - * File: UndirectedGraph.java - * Author: Keith Schwarz (htiek@cs.stanford.edu) - * - * A class representing an undirected graph where each edge has an associated - * real-valued length. Internally, the class is represented by an adjacency - * list where each edges appears twice - once in the forward direction and - * once in the reverse. In fact, this implementation was formed by taking - * a standard adjacency list and then duplicating the logic to ensure each - * edge appears twice. - */ -@SuppressWarnings({"unused", "unchecked"}) -public final class GrafoNoDirigido implements Iterable { - /* A map from nodes in the graph to sets of outgoing edges. Each - * set of edges is represented by a map from edges to doubles. - */ - private final Map> mGraph = new HashMap<>(); - - /** - * Adds a new node to the graph. If the node already exists, this - * function is a no-op. - * - * @param node The node to add. - * @return Whether or not the node was added. - */ - public boolean addNode(T node) { - /* If the node already exists, don't do anything. */ - if (mGraph.containsKey(node)) - return false; - - /* Otherwise, add the node with an empty set of outgoing edges. */ - mGraph.put(node, new HashSet<>()); - return true; - } - - /** - * Remove a node from the graph. - * - * @param node The node to remove. - * @return Whether or not the node was removed. - */ - public boolean removeNode(T node) { - /* If the node already exists, don't do anything. */ - if (!mGraph.containsKey(node)) - return false; - - /* Otherwise, remove the node. */ - mGraph.remove(node); - return true; - } - - /** - * Given a node, returns whether that node exists in the graph. - * - * @param node The node in question. - * @return Whether that node eixsts in the graph. - */ - public boolean nodeExists(T node) { - return mGraph.containsKey(node); - } - - /** - * Given two nodes, adds an arc of that length between those nodes. If - * either endpoint does not exist in the graph, throws a - * NoSuchElementException. - * - * @param one The first node. - * @param two The second node. - * @throws NoSuchElementException If either the start or destination nodes - * do not exist. - */ - public void addEdge(T one, T two) { - /* Confirm both endpoints exist. */ - if (!mGraph.containsKey(one) || !mGraph.containsKey(two)) - throw new NoSuchElementException("Both nodes must be in the graph."); - - /* Add the edge in both directions. */ - mGraph.get(one).add(two); - mGraph.get(two).add(one); - } - - /** - * Removes the edge between the indicated endpoints from the graph. If the - * edge does not exist, this operation is a no-op. If either endpoint does - * not exist, this throws a NoSuchElementException. - * - * @param one The start node. - * @param two The destination node. - * @throws NoSuchElementException If either node is not in the graph. - */ - public void removeEdge(T one, T two) { - /* Confirm both endpoints exist. */ - if (!mGraph.containsKey(one) || !mGraph.containsKey(two)) - throw new NoSuchElementException("Both nodes must be in the graph."); - - /* Remove the edges from both adjacency lists. */ - mGraph.get(one).remove(two); - mGraph.get(two).remove(one); - } - - /** - * Given two endpoints, returns whether an edge exists between them. If - * either endpoint does not exist in the graph, throws a - * NoSuchElementException. - * - * @param one The first endpoint. - * @param two The second endpoint. - * @return Whether an edge exists between the endpoints. - * @throws NoSuchElementException If the endpoints are not nodes in the - * graph. - */ - public boolean edgeExists(T one, T two) { - /* Confirm both endpoints exist. */ - if (!mGraph.containsKey(one) || !mGraph.containsKey(two)) - throw new NoSuchElementException("Both nodes must be in the graph."); - - /* Graph is symmetric, so we can just check either endpoint. */ - return mGraph.get(one).contains(two); - } - - /** - * Given a node in the graph, returns an immutable view of the edges - * leaving that node. - * - * @param node The node whose edges should be queried. - * @return An immutable view of the edges leaving that node. - * @throws NoSuchElementException If the node does not exist. - */ - public Set edgesFrom(T node) { - /* Check that the node exists. */ - Set arcs = mGraph.get(node); - if (arcs == null) - throw new NoSuchElementException("Source node does not exist."); - - return Collections.unmodifiableSet(arcs); - } - - /** - * Returns whether a given node is contained in the graph. - * - * @param node The node to test for inclusion. - * @return Whether that node is contained in the graph. - */ - public boolean containsNode(T node) { - return mGraph.containsKey(node); - } - - /** - * Returns an iterator that can traverse the nodes in the graph. - * - * @return An iterator that traverses the nodes in the graph. - */ - public Iterator iterator() { - return mGraph.keySet().iterator(); - } - - /** - * Returns the number of nodes in the graph. - * - * @return The number of nodes in the graph. - */ - public int size() { - return mGraph.size(); - } - - /** - * Returns whether the graph is empty. - * - * @return Whether the graph is empty. - */ - public boolean isEmpty() { - return mGraph.isEmpty(); - } - - /** - * Returns a human-readable representation of the graph. - * - * @return A human-readable representation of the graph. - */ - public String toString() { - return mGraph.toString(); - } -} - -class Node { - private int value; - - public Node(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } -} \ No newline at end of file diff --git a/src/cl/cromer/estructuras/GrafoNodo.java b/src/cl/cromer/estructuras/GrafoNodo.java new file mode 100644 index 0000000..dd1d95d --- /dev/null +++ b/src/cl/cromer/estructuras/GrafoNodo.java @@ -0,0 +1,20 @@ +package cl.cromer.estructuras; + +/** + * Created by cromer on 7/7/16. + */ +class GrafoNodo { + private int value; + + public GrafoNodo(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } +} diff --git a/src/cl/cromer/estructuras/MenuController.java b/src/cl/cromer/estructuras/MenuController.java index 5d0898d..9768d02 100644 --- a/src/cl/cromer/estructuras/MenuController.java +++ b/src/cl/cromer/estructuras/MenuController.java @@ -225,15 +225,31 @@ public class MenuController extends VBox implements Initializable { ); } + /** + * Click en Grafo Dirigidos. + */ + @FXML + protected void menuGrafoDirigidos() { + Grafo.Tipos grafoTipos = new Grafo.Tipos(Grafo.Tipos.DIRIGIDO); + loadStage( + resourceBundle.getString("tituloGrafoDirigido"), + "/cl/cromer/estructuras/fxml/grafo.fxml", + "/cl/cromer/estructuras/css/main.css", + grafoTipos + ); + } + /** * Click en Grafo No Dirigidos. */ @FXML protected void menuGrafoNoDirigidos() { + Grafo.Tipos grafoTipos = new Grafo.Tipos(Grafo.Tipos.NO_DIRIGIDO); loadStage( resourceBundle.getString("tituloGrafoNoDirigido"), "/cl/cromer/estructuras/fxml/grafo.fxml", - "/cl/cromer/estructuras/css/main.css" + "/cl/cromer/estructuras/css/main.css", + grafoTipos ); } diff --git a/src/cl/cromer/estructuras/fxml/menu.fxml b/src/cl/cromer/estructuras/fxml/menu.fxml index 9b283d4..34001dc 100644 --- a/src/cl/cromer/estructuras/fxml/menu.fxml +++ b/src/cl/cromer/estructuras/fxml/menu.fxml @@ -32,7 +32,7 @@ - +