From 61ce9e2a705becd6b75273d9249a6abad401df9a Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Thu, 7 Jul 2016 14:23:04 -0400 Subject: [PATCH] Many changes. --- src/cl/cromer/estructuras/Arbol.java | 81 +- .../cromer/estructuras/ArbolController.java | 29 +- .../cromer/estructuras/ArrayController.java | 1 - src/cl/cromer/estructuras/ColaController.java | 1 - .../cromer/estructuras/GrafoController.java | 301 +++++ src/cl/cromer/estructuras/GrafoDirigido.java | 1016 +++++++++++++++++ .../cromer/estructuras/GrafoNoDirigido.java | 187 +++ .../estructuras/ListaEnlazdaController.java | 1 - src/cl/cromer/estructuras/Logs.java | 16 + src/cl/cromer/estructuras/Main.java | 1 + src/cl/cromer/estructuras/MenuController.java | 18 +- src/cl/cromer/estructuras/PilaController.java | 1 - .../estructuras/bundles/Idioma_en.properties | 11 + .../estructuras/bundles/Idioma_es.properties | 11 + src/cl/cromer/estructuras/fxml/grafo.fxml | 38 + src/cl/cromer/estructuras/fxml/menu.fxml | 2 +- 16 files changed, 1639 insertions(+), 76 deletions(-) create mode 100644 src/cl/cromer/estructuras/GrafoController.java create mode 100644 src/cl/cromer/estructuras/GrafoDirigido.java create mode 100644 src/cl/cromer/estructuras/GrafoNoDirigido.java create mode 100644 src/cl/cromer/estructuras/fxml/grafo.fxml diff --git a/src/cl/cromer/estructuras/Arbol.java b/src/cl/cromer/estructuras/Arbol.java index 4a63d39..80787da 100644 --- a/src/cl/cromer/estructuras/Arbol.java +++ b/src/cl/cromer/estructuras/Arbol.java @@ -8,7 +8,6 @@ public class Arbol { private ArbolNodo arbol; private int size; private int altura; - private int ancho; private List> niveles; public enum PrimerLado { @@ -19,14 +18,12 @@ public class Arbol { public Arbol() { this.arbol = null; this.altura = 0; - this.ancho = 0; this.niveles = new ArrayList<>(); } public boolean insertar(int valor) { if (this.arbol == null) { arbol = new ArbolNodo(valor, null); - setAncho(1); setAltura(1); return true; } @@ -51,16 +48,13 @@ public class Arbol { nuevo.setPadre(padre); padre.setIzquerda(nuevo); size++; - if (primerLado == PrimerLado.IZQUERDA) { - setAncho(getAncho() + 1); - } setAltura(getAlturaRecursivo(arbol)); niveles = new ArrayList<>(); - for (int i = 0; i < getAltura(); i++) { + for (int i = 0; i <= getAltura(); i++) { niveles.add(new ArrayList<>()); } - getNivelesRecursivo(arbol); + calcularNiveles(arbol, 0); return true; } @@ -75,16 +69,13 @@ public class Arbol { nuevo.setPadre(padre); padre.setDerecha(nuevo); size++; - if (primerLado == PrimerLado.DERECHA) { - setAncho(getAncho() + 1); - } setAltura(getAlturaRecursivo(arbol)); niveles = new ArrayList<>(); - for (int i = 0; i < getAltura(); i++) { + for (int i = 0; i <= getAltura(); i++) { niveles.add(new ArrayList<>()); } - getNivelesRecursivo(arbol); + calcularNiveles(arbol, 0); return true; } @@ -113,15 +104,6 @@ public class Arbol { return niveles; } - public int getAncho() { - return ancho; - } - - public void setAncho(int ancho) { - //this.ancho = ancho; - this.ancho = (int) Math.pow(2, altura - 1) - 1; - } - public int getAlturaRecursivo(ArbolNodo nodo) { if (nodo == null) { return 0; @@ -130,53 +112,32 @@ public class Arbol { int alturaIzquerda = getAlturaRecursivo(nodo.getIzquerda()); int alturaDercha = getAlturaRecursivo(nodo.getDerecha()); if (alturaIzquerda > alturaDercha) { - nodo.setNivel(alturaIzquerda); return (alturaIzquerda + 1); } else { - nodo.setNivel(alturaDercha); return (alturaDercha + 1); } } } - public int getNivelesRecursivo(ArbolNodo nodo) { - if (nodo == null) { - return 0; + public void calcularNiveles(ArbolNodo nodo, int nivel) { + try { + if (nodo != null) { + nodo.setNivel(nivel); + niveles.get(nivel).add(nodo); + nivel++; + calcularNiveles(nodo.getIzquerda(), nivel); + calcularNiveles(nodo.getDerecha(), nivel); + } + else if (nivel != getAltura()) { + niveles.get(nivel).add(null); + nivel++; + calcularNiveles(null, nivel); + calcularNiveles(null, nivel); + } } - else { - try { - int alturaIzquerda = getNivelesRecursivo(nodo.getIzquerda()); - int alturaDerecha = getNivelesRecursivo(nodo.getDerecha()); - if (alturaIzquerda > alturaDerecha) { - if (!niveles.get(niveles.size() - alturaIzquerda - 1).contains(nodo)) { - niveles.get(niveles.size() - alturaIzquerda - 1).add(nodo); - } - if (nodo.getDerecha() == null) { - niveles.get(niveles.size() - nodo.getNivel() - 1).add(null); - } - if (nodo.getIzquerda() == null) { - niveles.get(niveles.size() - nodo.getNivel() - 1).add(null); - } - return (alturaIzquerda + 1); - } - else { - if (!niveles.get(niveles.size() - alturaDerecha - 1).contains(nodo)) { - niveles.get(niveles.size() - alturaDerecha - 1).add(nodo); - } - if (nodo.getDerecha() == null) { - niveles.get(niveles.size() - nodo.getNivel() - 1).add(null); - } - if (nodo.getIzquerda() == null) { - niveles.get(niveles.size() - nodo.getNivel() - 1).add(null); - } - return (alturaDerecha + 1); - } - } - catch (Exception exception) { - Logs.log(Level.SEVERE, exception); - return 0; - } + catch (Exception exception) { + Logs.log(Level.SEVERE, exception); } } diff --git a/src/cl/cromer/estructuras/ArbolController.java b/src/cl/cromer/estructuras/ArbolController.java index c003dd8..da40790 100644 --- a/src/cl/cromer/estructuras/ArbolController.java +++ b/src/cl/cromer/estructuras/ArbolController.java @@ -115,7 +115,6 @@ public class ArbolController implements Initializable { } catch (NumberFormatException exception) { // El error no es fatal, sigue - Logs.log(Level.WARNING, "No es tipo int."); Main.mostrarError(resourceBundle.getString("arbolNoValor"), resourceBundle); } } @@ -145,21 +144,31 @@ public class ArbolController implements Initializable { List> niveles = arbol.getNiveles(); - Colores colores = new Colores(); - int k = niveles.get(niveles.size() - 1).size(); - for (int i = niveles.size() - 1; i >= 0 ; i--) { - int l = k - niveles.get(i).size(); - if (i != niveles.size() - 1) { - l--; + int altura = arbol.getAltura() - 1; + int ancho = (int) Math.pow(2, altura) + (int) ((Math.pow(2, altura)) - 1); + System.out.println(ancho); + + Text text; + for (int i = 0; i < altura; i++) { + contenidoArbol.addRow(i); + for (int j = 0; j < ancho; j++) { + contenidoArbol.addColumn(j); + text = new Text(); + text.setText(" "); + text.setId(j + "_" + i); + contenidoArbol.add(text, j, i); } + } + + Colores colores = new Colores(); + for (int i = niveles.size() - 1; i >= 0 ; i--) { for (int j = 0; j < niveles.get(i).size(); j++) { - contenidoArbol.add(Grafico.crearCirculo(colores, j + "_" + i), l, i); + contenidoArbol.add(Grafico.crearCirculo(colores, j + "_" + i), j, i); colores.siguinteColor(); if (niveles.get(i).get(j) != null) { - Text text = (Text) scene.lookup("#texto_" + j + "_" + i); + text = (Text) scene.lookup("#texto_" + j + "_" + i); text.setText(String.valueOf(niveles.get(i).get(j).getValor())); } - l++; } } } diff --git a/src/cl/cromer/estructuras/ArrayController.java b/src/cl/cromer/estructuras/ArrayController.java index 07a8d62..eb168dc 100644 --- a/src/cl/cromer/estructuras/ArrayController.java +++ b/src/cl/cromer/estructuras/ArrayController.java @@ -219,7 +219,6 @@ public class ArrayController implements Initializable { } catch (NumberFormatException exception) { // El error no es fatal, sigue - Logs.log(Level.WARNING, "No es tipo int."); Main.mostrarError(resourceBundle.getString("arrayNoValor"), resourceBundle); } } diff --git a/src/cl/cromer/estructuras/ColaController.java b/src/cl/cromer/estructuras/ColaController.java index c43d66d..d54dba5 100644 --- a/src/cl/cromer/estructuras/ColaController.java +++ b/src/cl/cromer/estructuras/ColaController.java @@ -131,7 +131,6 @@ public class ColaController implements Initializable { } catch (NumberFormatException exception) { // El error no es fatal, sigue - Logs.log(Level.WARNING, "No es tipo int."); Main.mostrarError(resourceBundle.getString("colaNoValor"), resourceBundle); } } diff --git a/src/cl/cromer/estructuras/GrafoController.java b/src/cl/cromer/estructuras/GrafoController.java new file mode 100644 index 0000000..ea3cbdf --- /dev/null +++ b/src/cl/cromer/estructuras/GrafoController.java @@ -0,0 +1,301 @@ +package cl.cromer.estructuras; + +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.text.Text; + +import java.net.URL; +import java.util.ResourceBundle; +import java.util.logging.Level; + +/** + * Esta clase es para controlar todos la interfaz de Arbol. + * + * @author Chris Cromer + */ +public class GrafoController implements Initializable { + /** + * La caja para el valor. + */ + @FXML + private TextFieldLimited valorGrafo; + + /** + * La caja por nodo 1. + */ + @FXML + private TextFieldLimited valorNodo1; + + /** + * La caja por nodo 2. + */ + @FXML + private TextFieldLimited valorNodo2; + + /** + * Donde poner el contenido de array. + */ + @FXML + private Canvas contenidoGrafo; + + /** + * Donde va el codigo a mostrar a la pantalla. + */ + @FXML + private Text codigoGrafo; + + /** + * La escena donde está cosas graficas. + */ + private Scene scene; + + /** + * Donde está guardado los idiomas. + */ + private ResourceBundle resourceBundle; + + /** + * El arbol usado en la aplicación. + */ + private GrafoNoDirigido grafoNoDirigido; + + /** + * Grafico rectangulos. + */ + private Grafico grafico; + + /** + * Nodos. + */ + private Node[] nodes; + + /** + * Inicializar todos los datos y dibujar las graficas. + * + * @param location URL: El URL de fxml en uso. + * @param resourceBundle ResourceBundle: Tiene datos de idioma. + */ + @Override + public void initialize(URL location, ResourceBundle resourceBundle) { + this.resourceBundle = resourceBundle; + + grafoNoDirigido = null; + scene = null; + } + + /** + * Insertar un valor al array y mostrar el codigo en la pantalla. + */ + @FXML + protected void botonInsertar() { + if (scene == null) { + initializeGrafo(); + } + + // Mostrar el codigo + /*String codigoTexto = new Scanner(getClass().getResourceAsStream("/cl/cromer/estructuras/code/array" + tipo + "/insertar")).useDelimiter("\\Z").next(); + codigoArray.setText(codigoTexto);*/ + + if (valorGrafo.getText() != null && ! valorGrafo.getText().trim().equals("")) { + try { + int i; + for (i = 0; i < 5; i++) { + if (nodes[i] == null) { + nodes[i] = new Node(Integer.valueOf(valorGrafo.getText())); + break; + } + else if (nodes[i].getValue() == Integer.valueOf(valorGrafo.getText())) { + i = 5; + break; + } + } + + if (i == 5) { + // Maximo 5 nodos + Main.mostrarError(resourceBundle.getString("grafoLleno"), resourceBundle); + } + else { + boolean exito = grafoNoDirigido.addNode(nodes[i]); + if (exito) { + valorGrafo.setText(""); + generarGrafico(); + } + else { + Main.mostrarError(resourceBundle.getString("arbolValorExiste"), resourceBundle); + } + } + } + catch (NumberFormatException exception) { + // El error no es fatal, sigue + Main.mostrarError(resourceBundle.getString("arbolNoValor"), resourceBundle); + } + } + else { + Main.mostrarError(resourceBundle.getString("arbolNoValor"), resourceBundle); + } + } + + /** + * Insertar un valor al array y mostrar el codigo en la pantalla. + */ + @FXML + protected void botonInsertarEdge() { + if (scene == null) { + initializeGrafo(); + } + + if (valorNodo1.getText() != null && ! valorNodo1.getText().trim().equals("") && valorNodo2.getText() != null && ! valorNodo2.getText().trim().equals("")) { + + } + else { + // TODO: Error no nodos + } + + generarGrafico(); + } + + /** + * Crear un arbol nuevo. + */ + private void initializeGrafo() { + scene = contenidoGrafo.getScene(); + grafico = new Grafico(scene); + this.grafoNoDirigido = new GrafoNoDirigido<>(); + this.nodes = new Node[5]; + } + + private void generarGrafico() { + grafico.removerDestacar(); + + Colores colores = new Colores(); + + GraphicsContext graphicsContext = contenidoGrafo.getGraphicsContext2D(); + graphicsContext.clearRect(0, 0, contenidoGrafo.getWidth(), contenidoGrafo.getHeight()); + + if (nodes[0] != null) { + graphicsContext.setFill(colores.getFondo()); + graphicsContext.setStroke(colores.getBorder()); + + graphicsContext.fillOval(10, 10, 40, 40); + 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); + } + colores.siguinteColor(); + + if (nodes[1] != null) { + graphicsContext.setFill(colores.getFondo()); + graphicsContext.setStroke(colores.getBorder()); + + graphicsContext.fillOval(210, 10, 40, 40); + graphicsContext.strokeOval(210, 10, 40, 40); + + graphicsContext.setStroke(colores.getTexto()); + graphicsContext.strokeText(String.valueOf(nodes[1].getValue()), 225, 35); + } + colores.siguinteColor(); + + if (nodes[2] != null) { + graphicsContext.setFill(colores.getFondo()); + graphicsContext.setStroke(colores.getBorder()); + + graphicsContext.fillOval(10, 210, 40, 40); + graphicsContext.strokeOval(10, 210, 40, 40); + + graphicsContext.setStroke(colores.getTexto()); + graphicsContext.strokeText(String.valueOf(nodes[2].getValue()), 25, 235); + } + colores.siguinteColor(); + + if (nodes[3] != null) { + graphicsContext.setFill(colores.getFondo()); + graphicsContext.setStroke(colores.getBorder()); + + graphicsContext.fillOval(210, 210, 40, 40); + graphicsContext.strokeOval(210, 210, 40, 40); + + graphicsContext.setStroke(colores.getTexto()); + graphicsContext.strokeText(String.valueOf(nodes[3].getValue()), 225, 235); + } + colores.siguinteColor(); + + if (nodes[4] != null) { + graphicsContext.setFill(colores.getFondo()); + graphicsContext.setStroke(colores.getBorder()); + + graphicsContext.fillOval(105, 410, 40, 40); + graphicsContext.strokeOval(105, 410, 40, 40); + + graphicsContext.setStroke(colores.getTexto()); + graphicsContext.strokeText(String.valueOf(nodes[4].getValue()), 120, 435); + } + + graphicsContext.setStroke(colores.getBorder()); + + // 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[1] != null && grafoNoDirigido.edgeExists(nodes[0], nodes[1])) { + 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); + } + } + + /** + * Calcular la posición del texto basado en la cantidad de caracters. + * + * @param x int: La posición donde desea el texto. + * @param texto String: El texto a posicionar. + * + * @return int: La posición nueva. + */ + private int textX(int x, String texto) { + if (texto.length() == 1) { + return x; + } + else if (texto.length() == 2) { + return x - 3; + } + else { + return x - 7; + } + } +} \ No newline at end of file diff --git a/src/cl/cromer/estructuras/GrafoDirigido.java b/src/cl/cromer/estructuras/GrafoDirigido.java new file mode 100644 index 0000000..da3ce48 --- /dev/null +++ b/src/cl/cromer/estructuras/GrafoDirigido.java @@ -0,0 +1,1016 @@ +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 new file mode 100644 index 0000000..f7a45c4 --- /dev/null +++ b/src/cl/cromer/estructuras/GrafoNoDirigido.java @@ -0,0 +1,187 @@ +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; + } + + /** + * 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/ListaEnlazdaController.java b/src/cl/cromer/estructuras/ListaEnlazdaController.java index 8ca237f..9cf4f51 100644 --- a/src/cl/cromer/estructuras/ListaEnlazdaController.java +++ b/src/cl/cromer/estructuras/ListaEnlazdaController.java @@ -265,7 +265,6 @@ public class ListaEnlazdaController implements Initializable { } catch (NumberFormatException exception) { // El error no es fatal, sigue - Logs.log(Level.WARNING, "No es tipo int."); Main.mostrarError(resourceBundle.getString("listaNoValor"), resourceBundle); } } diff --git a/src/cl/cromer/estructuras/Logs.java b/src/cl/cromer/estructuras/Logs.java index edbbce1..48315f2 100644 --- a/src/cl/cromer/estructuras/Logs.java +++ b/src/cl/cromer/estructuras/Logs.java @@ -73,6 +73,22 @@ public class Logs { } } + /** + * Agregar un log al logger con un mensaje. + * + * @param mensaje String: El mensaje de lo que pasó. + */ + static public void log(String mensaje) { + if (DEBUG) { + if (DEBUG_TIPO == DEBUG_TIPOS.ARCHIVO) { + Logger.getLogger(LOGNAME).log(Level.INFO, mensaje); + } + else { + System.out.println(mensaje + "\n"); + } + } + } + /** * Agregar un log al logger con un mensaje. * diff --git a/src/cl/cromer/estructuras/Main.java b/src/cl/cromer/estructuras/Main.java index f29f1f8..ef1c693 100644 --- a/src/cl/cromer/estructuras/Main.java +++ b/src/cl/cromer/estructuras/Main.java @@ -114,6 +114,7 @@ public class Main extends Application { dialog.setContentText(mensaje); dialog.getDialogPane().getButtonTypes().add(botonCerrar); dialog.getDialogPane().getScene().getWindow().sizeToScene(); + dialog.getDialogPane().setPrefWidth(mensaje.length() * 8); Main.setIcon(dialog, Main.class); dialog.show(); } diff --git a/src/cl/cromer/estructuras/MenuController.java b/src/cl/cromer/estructuras/MenuController.java index 21b5409..5d0898d 100644 --- a/src/cl/cromer/estructuras/MenuController.java +++ b/src/cl/cromer/estructuras/MenuController.java @@ -218,13 +218,25 @@ public class MenuController extends VBox implements Initializable { protected void menuArbolGeneral() { Arbol.Tipos arbolTipos = new Arbol.Tipos(Arbol.Tipos.GENERAL); loadStage( - resourceBundle.getString("tituloCola"), + resourceBundle.getString("tituloArbolGeneral"), "/cl/cromer/estructuras/fxml/arbol.fxml", "/cl/cromer/estructuras/css/main.css", arbolTipos ); } + /** + * Click en Grafo No Dirigidos. + */ + @FXML + protected void menuGrafoNoDirigidos() { + loadStage( + resourceBundle.getString("tituloGrafoNoDirigido"), + "/cl/cromer/estructuras/fxml/grafo.fxml", + "/cl/cromer/estructuras/css/main.css" + ); + } + /** * Click en Hash Table. */ @@ -250,6 +262,8 @@ public class MenuController extends VBox implements Initializable { dialog.getDialogPane().getButtonTypes().add(botonCancelar); dialog.getDialogPane().getButtonTypes().add(botonCambiar); dialog.getDialogPane().getScene().getWindow().sizeToScene(); + dialog.getDialogPane().setPrefHeight(125); + dialog.getDialogPane().setPrefWidth(400); Main.setIcon(dialog, getClass()); Optional result = dialog.showAndWait(); @@ -275,6 +289,8 @@ public class MenuController extends VBox implements Initializable { dialog.getDialogPane().getButtonTypes().add(botonCancelar); dialog.getDialogPane().getButtonTypes().add(botonCambiar); dialog.getDialogPane().getScene().getWindow().sizeToScene(); + dialog.getDialogPane().setPrefHeight(125); + dialog.getDialogPane().setPrefWidth(400); Main.setIcon(dialog, getClass()); Optional result = dialog.showAndWait(); diff --git a/src/cl/cromer/estructuras/PilaController.java b/src/cl/cromer/estructuras/PilaController.java index 9d60bcf..81485af 100644 --- a/src/cl/cromer/estructuras/PilaController.java +++ b/src/cl/cromer/estructuras/PilaController.java @@ -131,7 +131,6 @@ public class PilaController implements Initializable { } catch (NumberFormatException exception) { // El error no es fatal, sigue - Logs.log(Level.WARNING, "No es tipo int."); Main.mostrarError(resourceBundle.getString("pilaNoValor"), resourceBundle); } } diff --git a/src/cl/cromer/estructuras/bundles/Idioma_en.properties b/src/cl/cromer/estructuras/bundles/Idioma_en.properties index df24b6a..b1711a2 100644 --- a/src/cl/cromer/estructuras/bundles/Idioma_en.properties +++ b/src/cl/cromer/estructuras/bundles/Idioma_en.properties @@ -12,6 +12,9 @@ tituloMerge=Merge tituloListaEnlazadaSimple=Simple Linked List tituloListaEnlazadaCircular=Circular Linked List tituloListaEnlazadaDoble=Double Linked List +tituloArbolGeneral=General Tree +tituloGrafoDirigido=Grafo Dirigido +tituloGrafoNoDirigido=Grafo No Dirigido tituloTablaHash=Hash Table estructuras=Structures @@ -89,6 +92,14 @@ colaNoValor=Please input a numeric value. arbolValorExiste=Value already exists. arbolNoEsta=Value does not exist. arbolNoValor=Please input a numeric value. + +grafoNodos=Nodos: +grafoEdges=Edges: +grafoLleno=Node not inserted because of a maxium of 5 nodes in this implementation. +grafoNodoExiste=Node alredy exists. +grafoNoEsta=Node does not exist. +grafoNoNodo=Please input a numeric node number. + tablaHashLleno=Key not inserted because the hash table is full. tablaHashLlaveExiste=Key already exists. tablaHashNoEsta=Key does not exist. diff --git a/src/cl/cromer/estructuras/bundles/Idioma_es.properties b/src/cl/cromer/estructuras/bundles/Idioma_es.properties index 3239503..0747205 100644 --- a/src/cl/cromer/estructuras/bundles/Idioma_es.properties +++ b/src/cl/cromer/estructuras/bundles/Idioma_es.properties @@ -12,6 +12,9 @@ tituloMerge=Merge tituloListaEnlazadaSimple=Lista Enlazada Simple tituloListaEnlazadaCircular=Lista Enlazada Circular tituloListaEnlazadaDoble=Lista Enlazada Doble +tituloArbolGeneral=Arbol General +tituloGrafoDirigido=Grafo Dirigido +tituloGrafoNoDirigido=Grafo No Dirigido tituloTablaHash=Tabla Hash estructuras=Estructuras array=Array @@ -88,6 +91,14 @@ colaNoValor=Ingresar un valor num\u00E9rico por favor. arbolValorExiste=El valor ya existe. arbolNoEsta=El valor no existe. arbolNoValor=Ingresar un valor num\u00E9rico por favor. + +grafoNodos=Nodos: +grafoEdges=Edges: +grafoLleno=El nodo no fue insertado porque esta implementaci\u00F3n tiene un maxiumo de 5 nodos. +grafoNodoExiste=El nodo ya existe. +grafoNoEsta=El nodo no existe. +grafoNoNodo=Ingresar una llave y un valor num\u00E9rico por favor. + tablaHashLleno=La llave no fue insertado porque la tabla hash est\u00E1 lleno. tablaHashLlaveExiste=La llave ya existe. tablaHashNoEsta=La llave no existe. diff --git a/src/cl/cromer/estructuras/fxml/grafo.fxml b/src/cl/cromer/estructuras/fxml/grafo.fxml new file mode 100644 index 0000000..3e9c64b --- /dev/null +++ b/src/cl/cromer/estructuras/fxml/grafo.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + +