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