Sie sind auf Seite 1von 28

Algoritmo de Kruskal

El algoritmo de Kruskal es un algoritmo de la teora de grafos para encontrar un rbol


recubridor mnimo en un grafo conexo y ponderado. Es decir, busca un subconjunto de
aristas que, formando un rbol, incluyen todos los vrtices y donde el valor total de todas
las aristas del rbol es el mnimo. Si el grafo no es conexo, entonces busca un bosque
expandido mnimo (un rbol expandido mnimo para cada componente conexa). El
algoritmo de Kruskal es un ejemplo de algoritmo voraz.

Un ejemplo de rbol expandido mnimo. Cada punto representa un vrtice, el cual puede ser
un rbol por s mismo. Se usa el Algoritmo para buscar las distancias ms cortas (rbol
expandido) que conectan todos los puntos o vrtices.
Funciona de la siguiente manera:

se crea un bosque B (un conjunto de rboles), donde cada vrtice del grafo es un
rbol separado
se crea un conjunto C que contenga a todas las aristas del grafo
mientras C es no vaco
o eliminar una arista de peso mnimo de C
o si esa arista conecta dos rboles diferentes se aade al bosque, combinando
los dos rboles en un solo rbol
o en caso contrario, se desecha la arista

Al acabar el algoritmo, el bosque tiene un solo componente, el cual forma un rbol de


expansin mnimo del grafo.
Este algoritmo fue publicado por primera vez en Proceedings of the American
Mathematical Society, pp. 4850 en 1956, y fue escrito por Joseph Kruskal.

Implementacin del Algoritmo de Kruskal


en Java
De Wikilibros, la coleccin de libros de texto de contenido libre.
Saltar a: navegacin, buscar

El algoritmo de Kruskal es un algoritmo de la teora de grafos que busca encontrar un


rbol recubridor mnimo de un grafo dado. Aqu encontraremos una implementacin en
Java incluyendo una interfaz grfica.

Contenido
[ocultar]

1 Descripcin del Problema


2 Limitaciones
3 Solucin
o 3.1 Estructura Grafo
3.1.1 Clase Enlace
3.1.2 Clase Nodo
3.1.3 Clase Arco
3.1.4 Clase Grafo
o 3.2 Interfaz Grfica
3.2.1 Clase Lienzo
3.2.2 Clase Punto
3.2.3 Clase Arista
o 3.3 Paquete Principal
3.3.1 Clase AlgoritmoKruskal
o 3.4 VENTANA
3.4.1 Clase Aplicacin
4 Modo de compilacin y ejecucin
5 Pruebas
6 Tiempo empleado
7 Tiempo de Ejecucin T(n)
8 Conclusiones
9 Vase tambin
10 Enlaces externos

Descripcin del Problema[editar]


El algoritmo de kruskal, es un algoritmo voraz utilizado en la teora de grafos, con el fin de
encontrar un rbol recubridor mnimo de un grafo conexo y ponderado.
El algoritmo de kruskal consiste en:

Paso 0: Iniciar el rbol T con n nodos y sin arcos


T=({1, 2, n},)

Paso 1: Con los arcos de G crear una lista L de arcos, en orden ascendente de peso. Los
arcos con el mismo peso son ordenados arbitrariamente.

Paso 2. Seleccionar el arco (i,j) que est al comienzo de L. Si ste forma un circuito en T no
se transfiere a T y se borra de L y se repite el paso 2. Si no forma circuito en T se transfiere
a T y se borra de L.

Paso 3. Si L es no vaco, volver al paso 2, de lo contrario PARAR.

Limitaciones[editar]
Las nicas limitaciones que se presentan con el problema de la implementacin del
algoritmo de Kruskal es la creacin de un algoritmo adicional que nos compruebe que al
adicionar una arista al grafo no nos haga un ciclo.
El algoritmo implementado es el siguiente:
public boolean HayCiclo(Grafo g,Arco aVerificar,Nodo terminal,String N)
{
ArrayList<Enlace> aux=terminal.getEnlaces();
if(aux.size()==0)
return false;
if(terminal.existeEnlace(aVerificar.getInicial())!=-1)
return true;
for(int i=0;i<aux.size();i++)
{
Enlace nodo=aux.get(i);
if(nodo.getDestino().equals(N)==false)
if(
HayCiclo(g,aVerificar,g.getNodo(nodo.getDestino()),terminal.getNombre()))
return
true;
}
return false;
}

Solucin[editar]
En la implementacin del algoritmo de Kruskal en Java, se hizo uso de una estructura de
datos adicional llamada grafo y adicionalmente se implement una interfaz grfica.

Estructura Grafo[editar]
Clase Enlace[editar]

// creamos un clase llamada enlace


La clase enlace se utiliza para hacer refencia al nodo terminal y al peso de un arco.
public class Enlace
{
private String destino;
private double peso;
public Enlace(String desti, double peso1)
{
destino = desti;
peso = peso1;
}
public Enlace(String desti)
{
destino = desti;
peso = -1;
}
public void modificar(double peso1)
{
peso = peso1;
}
public String getDestino()
{
return destino;
}
public double getPeso()
{
return peso;
}
}

Clase Nodo[editar]

Hace referencia a un nodo del grafo, guardando un nombre y una serie de enlaces a otros
nodos.
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class Nodo
{
private String nombre;
private ArrayList<Enlace> enlaces;
private int enlacesExistentes;

public ArrayList<Enlace> getEnlaces()


{
return enlaces;
}
public Nodo(String newName)
{
nombre = newName;
enlacesExistentes = -1;
enlaces = new ArrayList<Enlace>();
}
public int getEnlacesExistentes()
{
return enlacesExistentes;
}
public String getNombre()
{
return nombre;
}
public void agregarEnlace(String enlazar,double peso)
{
if (enlacesExistentes == -1)
{
enlaces.add(new Enlace(enlazar,peso));
enlacesExistentes++;
}
else
{
int posicion;
posicion = existeEnlace(enlazar);
if (posicion == -1)
{
enlaces.add(new Enlace(enlazar,peso));
enlacesExistentes++;
}
}
}
public int existeEnlace(String enlazar)
{
for (int i = 0; i < enlaces.size(); i++)
{
Enlace miEnlace;
miEnlace = enlaces.get(i);
if (miEnlace.getDestino().equals(enlazar))
return i;
}
return -1;
}
public double enlacePosicion(int posi)
{
Enlace miEnlace;

miEnlace = enlaces.get(posi);
return miEnlace.getPeso();
}
public String NodoPosicion(int posi)
{
Enlace miEnlace;
miEnlace = enlaces.get(posi);
return miEnlace.getDestino();
}
boolean eliminarEnlace(int posicion)
{
if (posicion >= 0 && posicion <= enlaces.size())
{
enlaces.remove(posicion);
enlacesExistentes--;
return true;
}
else
JOptionPane.showMessageDialog(null, "No hay
enlace en la posicion " + posicion);
return false;
}
}

Clase Arco[editar]

Guarda la referencia del nodo inicial, nodo terminal y peso de un determinado arco del
grafo.
public class Arco
{
private String inicial;
private String terminal;
private float peso;
public Arco(String ini, String ter, float pes)
{
inicial = ini;
terminal = ter;
peso = pes;
}
public float getPeso()
{
return peso;
}
public void setPeso(float peso)
{
this.peso = peso;
}
public String getInicial()
{

return inicial;
}
public void setInicial(String inicial)
{
this.inicial = inicial;
}
public String getTerminal()
{
return terminal;
}
public void setTerminal(String terminal)
{
this.terminal = terminal;
}
public String toString()
{
return "(" + inicial + ", " + terminal + ", " + peso +
")";
}
}

Clase Grafo[editar]

Representa la estructura grafo, compuesta por nodos y arcos.


import java.util.Hashtable;
import java.util.ArrayList;
public class Grafo
{
ArrayList <String>nombres;
ArrayList <Arco>aristas;
Hashtable <String,Nodo> nodos;
public Grafo()
{
nombres=new ArrayList<String>();
nodos=new Hashtable <String,Nodo>();
aristas=new ArrayList <Arco>();
}
public void ingresarNodo(String nombre)
{
nombres.add(nombre);
nodos.put(nombre,new Nodo(nombre));
}
public void adicionarEnlace(String nodoInicial,String
nodoTerminal,float peso)
{
Arco nuevo=new Arco(nodoInicial,nodoTerminal,peso);
int i=buscarIndice(nuevo.getPeso());

if(i==-1)
aristas.add(nuevo);
else
aristas.add(i,nuevo);
nodos.get(nodoInicial).agregarEnlace(nodoTerminal,peso);
nodos.get(nodoTerminal).agregarEnlace(nodoInicial,peso);
}
public boolean busarArista(Arco arco)
{
for(int i=0;i<aristas.size();i++)
{
Arco otro=aristas.get(i);
if(arco.getInicial().equals(otro.getInicial())&&arco.getTerminal().equals
(otro.getTerminal())&&arco.getPeso()==otro.getPeso())
{
aristas.remove(otro);
return true;
}
}
return false;
}
public int buscarIndice(float peso)
{
for(int i=0;i<aristas.size();i++)
{
if(peso<aristas.get(i).getPeso())
return i;
}
return -1;
}
public Hashtable getNodos()
{
return nodos;
}
public void setNodos(Hashtable<String,Nodo > muchos)
{
nodos=muchos;
}
public ArrayList<String> getNombres()
{
return nombres;
}
public Nodo getNodo(String nombre)
{
return (Nodo)nodos.get(nombre);
}
public ArrayList<Arco> getAristas() {
return aristas;
}
public void setAristas(ArrayList<Arco> aristas) {
this.aristas = aristas;
}

public void setNombres(ArrayList<String> nombres) {


this.nombres = nombres;
}
}

Interfaz Grfica[editar]
Clase Lienzo[editar]

Es el lienzo sobre el cual se dibujar el grafo.


import java.awt.*;
import java.util.ArrayList;
import javax.swing.JComponent;
public class Lienzo extends JComponent
{
private ArrayList<Punto> puntos;
private ArrayList<Arista> aristas;
private ArrayList<Arista> neo;
private Point a, b;
public boolean estado = false;
public boolean punto = false;
public Lienzo()
{
aristas = new ArrayList<Arista>();
puntos = new ArrayList<Punto>();
neo = new ArrayList<Arista>();
}
public void paintComponent(Graphics g)
{
if (punto)
{
g.setColor(Color.BLUE);
g.drawLine((int) a.getX() + 5, (int) a.getY() +
5, (int) b.getX() + 5, (int) b.getY() + 5);
}
for (int i = 0; i < aristas.size(); i++)
{
final Arista arista = (Arista) aristas.get(i);
arista.pintarRecta(g);
}
if (estado)
for (int i = 0; i < neo.size(); i++)
{
final Arista arista = (Arista)
neo.get(i);
arista.setColor(Color.RED);
arista.pintarRecta(g);
}
for (int i = 0; i < puntos.size(); i++)
{

final Punto punto = (Punto) puntos.get(i);


punto.pintarPunto(g);
}
}
public void cambiarGrafo(Grafo nuevo)
{
Arco aux;
for (int i = 0; i < aristas.size(); i++)
{
aux = aristas.get(i).getArista();
if (nuevo.busarArista(aux) == true)
neo.add(aristas.get(i));
}
for (int i = 0; i < aristas.size(); i++)
{
final Arco n = aristas.get(i).getArista();
nuevo.getAristas().add(n);
}
estado = true;
repaint();
}
public ArrayList<Punto> getPuntos()
{
return puntos;
}
public void setPuntos(final ArrayList<Punto> puntos)
{
this.puntos = puntos;
}
public ArrayList<Arista> getAristas()
{
return aristas;
}
public void setAristas(final ArrayList<Arista> aristas)
{
this.aristas = aristas;
}
public ArrayList<Arista> getNeo()
{
return neo;
}
public void setNeo(final ArrayList<Arista> neo)
{
this.neo = neo;
}

public void setA(Point a)


{
this.a = a;
}
public void setB(Point b)
{
this.b = b;
}
}

Clase Punto[editar]

Permite dibujar un punto sobre el lienzo. Hace referencia a la posicin del punto sobre el
lienzo.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public class Punto
{
private Point ubicacion;
private String nombre;
private Color colorPunto = Color.BLUE;
private static final int RADIO = 10;
public Punto(int x, int y, String nombre)
{
ubicacion = new Point(x, y);
this.nombre = nombre;
}
public void pintarPunto(Graphics g)
{
g.setColor(Color.BLACK);
g.drawString(nombre, ubicacion.x - 3, ubicacion.y - 3);
g.setColor(colorPunto);
g.fillOval(ubicacion.x, ubicacion.y, 10, 10);
}
public void pintarPunto(Graphics g, Color color)
{
g.setColor(Color.BLACK);
g.drawString(nombre, ubicacion.x - 3, ubicacion.y - 3);
g.setColor(color);
g.fillOval(ubicacion.x, ubicacion.y, 10, 10);
}
public boolean ecuacionDeCirculo(Point punto)
{
return (((punto.x - ubicacion.x) * (punto.x ubicacion.x) + (punto.y - ubicacion.y) * (punto.y - ubicacion.y)) <=
(RADIO * RADIO));
}

public Point getUbicacion()


{
return ubicacion;
}
public String getNombre()
{
return nombre;
}
public void setUbicacion(Point ubicacion)
{
this.ubicacion = ubicacion;
}
public Color getColorPunto()
{
return colorPunto;
}
public void setColorPunto(Color colorPunto)
{
this.colorPunto = colorPunto;
}
}

Clase Arista[editar]

Permite dibujar una arista entre dos puntos sobre el lienzo. Hace referencia a los puntos.
import
import
import
import
import

java.awt.Color;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Point;
java.awt.geom.QuadCurve2D;

public class Arista


{
private Arco arista;
private Punto a, b;
private Point inicial;
private Point terminal, ubicacionExt;
private Color color = new Color(0, 128, 128), aux = Color.RED;
private int tipo;
private float peso;
public Arista(Punto puntoA, Punto puntoB, int tipo, float peso)
{
arista = new Arco(puntoA.getNombre(), puntoB.getNombre(),
peso);
a = puntoA;
b = puntoB;
this.tipo = tipo;

this.peso = peso;
}
public void pintarRecta(Graphics ga)
{
inicial = a.getUbicacion();
terminal = b.getUbicacion();
Graphics2D g = (Graphics2D) ga;
double a = (inicial.y - terminal.y);
double b = (inicial.x - terminal.x);
double m = a / b;
double grado = Math.atan(m);
switch (tipo)
{
case 0:
g.setColor(color);
g.drawLine(inicial.x + 5, inicial.y + 5,
terminal.x + 5, terminal.y + 5);
g.setColor(aux);
g.drawString(peso + "", (inicial.x +
terminal.x) / 2, (inicial.y + terminal.y) / 2);
break;
case 1:
g.setColor(color);
g.drawOval(inicial.x - 10, inicial.y 30, 30, 30);
g.setColor(aux);
g.drawString(peso + "", inicial.x - 3,
inicial.y - 30);
break;
case 2:
Point control = null;
if (grado > 0)
{
if (grado <= 45 && grado >= 0)
control = new
Point((inicial.x + terminal.x) / 2 - 10, (inicial.y + terminal.y) / 2 +
50);
if (grado <= 90 && grado > 45)
control = new
Point((inicial.x + terminal.x) / 2 + 50, (inicial.y + terminal.y) / 2 +
10);
}
else
{
if (grado >= -45 && grado <= 0)
control = new
Point((inicial.x + terminal.x) / 2 - 30, (inicial.y + terminal.y) / 2 10);
if (grado >= -90 && grado < -45)
control = new
Point((inicial.x + terminal.x) / 2 - 50, (inicial.y + terminal.y) / 2 10);

}
Point tempInicial = new Point(inicial.x +
5, inicial.y + 5),
tempFinal = new Point(terminal.x + 5,
terminal.y + 5);
QuadCurve2D.Double quad = new
QuadCurve2D.Double();
quad.setCurve(tempInicial, control,
tempFinal);
g.setColor(aux);
g.drawString(peso + "", control.x,
control.y);
g.setColor(color);
g.draw(quad);
break;
}
}
public Point getUbicacion()
{
return ubicacionExt;
}
public int getTipo()
{
return tipo;
}
public Arco getArista()
{
return arista;
}
public void setArista(Arco arista)
{
this.arista = arista;
}
public void getColor()
{
color = new Color(0, 128, 128);
aux = Color.RED;
}
public void setColor(Color color)
{
if (color.equals(new Color(0, 128, 128)))
aux = Color.RED;
else
aux = Color.BLUE;

this.color = color;
}
}

Paquete Principal[editar]
Clase AlgoritmoKruskal[editar]
//Implementacin del Algoritmo voraz de Kruskal.
import java.util.ArrayList;
public class AlgoritmoKruskal
{
@SuppressWarnings("unchecked")
public Grafo aplicarKruskal(Grafo grafo)
{
Grafo rbol=new Grafo();
ArrayList<String> nodos=grafo.getNombres();
for(int j=0;j<nodos.size();j++)
{
rbol.ingresarNodo(nodos.get(j));
}
ArrayList<Arco>
L=(ArrayList<Arco>)grafo.getAristas().clone();
Arco pro=L.get(0);
rbol.adicionarEnlace(pro.getInicial(),
pro.getTerminal(), pro.getPeso());
L.remove(pro);
while(L.size()!=0)
{
pro=L.get(0);
if(HayCiclo(rbol,
pro,rbol.getNodo(pro.getTerminal()) , pro.getTerminal())==false)
rbol.adicionarEnlace(pro.getInicial(),
pro.getTerminal(), pro.getPeso());
L.remove(pro);
}
return rbol;
}
public boolean HayCiclo(Grafo g,Arco aVerificar,Nodo
terminal,String N)
{
ArrayList<Enlace> aux=terminal.getEnlaces();
if(aux.size()==0)
return false;

if(terminal.existeEnlace(aVerificar.getInicial())!=-1)
return true;
for(int i=0;i<aux.size();i++)
{
Enlace nodo=aux.get(i);
if(nodo.getDestino().equals(N)==false)
if(
HayCiclo(g,aVerificar,g.getNodo(nodo.getDestino()),terminal.getNombre()))
return true;
}
return false;
}
}

VENTANA[editar]

import java.awt.Color;
import
import
import
import
import
import
import
import
import
import
import
import

java.awt.Container;
java.awt.Cursor;
java.awt.Font;
java.awt.Point;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.ItemEvent;
java.awt.event.ItemListener;
java.awt.event.MouseEvent;
java.awt.event.MouseListener;
java.awt.event.MouseMotionListener;
java.util.ArrayList;

import
import
import
import
import
import
import
import
import
import

javax.swing.BorderFactory;
javax.swing.ButtonGroup;
javax.swing.JButton;
javax.swing.JComboBox;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JOptionPane;
javax.swing.JRadioButton;
javax.swing.JScrollPane;
javax.swing.JTextArea;

public class Ventana implements MouseListener, ItemListener,


ActionListener, MouseMotionListener
{
int cantidad = 0;
ArrayList<Punto> puntos;
ArrayList<Arista> aristas;
static JFrame frame;
JButton aplicar,nuevo,recuperar;
Container contenedor;

JRadioButton radioNodo, radioArista, radioMod;


JLabel ayuda, titulo;
ButtonGroup grupo;
JComboBox comboOpcionesRecta,ayudaCombo;
JScrollPane panel;
public JTextArea area;
String ayudaNod,ayudaAri,ayudaMod,ayudaRes,ayudaNue,ayudaApl;
Punto pun[];
public Lienzo lienzo;
Grafo grafo;
int j,i;
int x,y;
private int contador = 0;
public Ventana()
{
frame = new JFrame();
contenedor=frame.getContentPane();
Font font=new Font("Verdana",Font.BOLD,11);
Font font1=new Font("Verdana",Font.PLAIN,12);
grafo=new Grafo();
lienzo = new Lienzo();
lienzo.setBounds(0, 0, 600, 600);
lienzo.setBorder(BorderFactory.createBevelBorder(1));
lienzo.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
pun = new Punto[2];
pun[0]=null;
pun[1]=null;
puntos = new ArrayList<Punto>();
aristas = new ArrayList<Arista>();
area=new JTextArea();
area.setFont(font1);
panel=new JScrollPane(area);
panel.setBounds(660, 270, 280, 250);
titulo=new JLabel("Dibuje su grafo:");
titulo.setFont(font);
titulo.setBounds(610, 20, 130, 20);
ayuda=new JLabel("Ayuda:");
ayuda.setBounds(610, 200, 100, 20);
ayuda.setFont(font);
comboOpcionesRecta = new JComboBox();
comboOpcionesRecta.addItem("Arista");
comboOpcionesRecta.addItem("Arista Bucle");
comboOpcionesRecta.addItem("Arista Curva");
comboOpcionesRecta.setFont(font);
ayudaCombo=new JComboBox();

ayudaCombo.addItem(">Como hacer un Nodo");


ayudaCombo.addItem(">Como hacer una Arista");
ayudaCombo.addItem(">Como modificar un Grafo");
ayudaCombo.addItem(">Boton 'Nuevo'");
ayudaCombo.addItem(">Boton 'Aplicar'");
ayudaCombo.addItem(">Boton'Reset'");
ayudaCombo.setFont(font);
ayudaCombo.setSelectedIndex(-1);
radioNodo = new JRadioButton("Crear Nodo");
radioArista = new JRadioButton("Crear Arista");
radioMod = new JRadioButton("Modificar");
radioArista.setFont(font);
radioMod.setFont(font);
radioNodo.setFont(font);
grupo = new ButtonGroup();
grupo.add(radioNodo);
grupo.add(radioArista);
grupo.add(radioMod);
radioNodo.setSelected(true);
radioNodo.setBounds(680, 60, 120, 20);
radioArista.setBounds(680, 110, 130, 20);
radioMod.setBounds(820, 60, 100, 20);
aplicar=new JButton("Aplicar");
aplicar.setBounds(670,160, 80, 20);
aplicar.setFont(font);
nuevo=new JButton("Nuevo");
nuevo.setBounds(760,160, 80, 20);
nuevo.setFont(font);
recuperar=new JButton("Reset");
recuperar.setBounds(850,160, 80, 20);
recuperar.setFont(font);
comboOpcionesRecta.setBounds(815, 110, 100, 20);
ayudaCombo.setBounds(710,240,175,20);
ayudaNod = "\nCOMO CREAR UN NODO!!!\n\n" + "1.
Seleccione el RadioButton \"Crear Nodo\".\n" + "2. Haga doble click sobre
el area de Dibujo.\n" + "3. Inserte el nombre del Nodo.\n" + "4. Haga
click en Aceptar.";
ayudaAri = "\nCOMO CREAR UNA ARISTA!!!\n\n" + "1.
Seleccione el RadioButton \"Crear Arista\".\n" + "2. Seleccione el Tipo
de arista que desee\n
\"Arista\", \"Arista Curva\", o \"Arista
Bucle\".\n" + "3. Haga click sobre el nodo que desea sea el\n
nodo
inicial.\n" + "4. Mantega presionado el boton del mouse\n
y arrastrelo
hasta el nodo terminal.\n" + "5. Suelte el boton del mouse e ingrese\n
el peso de la Arista.\n" + "6. Haga click en Aceptar.";
ayudaMod = "\nCOMO MODIFICAR EL GRAFO!!!\n\n" + "1.
Seleccione el RadioButton \"Modificar\".\n" + "2. Haga click sobre un
Nodo\n" + "3. Mantega presionado el botn del mouse \n
y arrastrelo
para darle una nueva\n
posicin al nodo.\n" + "4. Suelte el botn del
mouse.";

ayudaRes = "\nBOTON RESET!!!\n\n" + " Este botn


permite recuperar el estado \n" + " del Grafo antes de aplicar el
Algoritmo de \n" + " Kruskal.\n";
ayudaApl = "\nBOTON APLICAR!!!\n\n" + " Este botn
permite Aplicar el Algoritmo de\n" + " Kruskal al Grafo dibujado por el
Usuario.";
ayudaNue = "\nBOTON NUEVO!!!\n\n" + " Limpia el area de
Dibujo para crear un\n" + " nuevo Grafo y poder aplicar nuevamente\n" + "
el Algoritmo de Kruskal.\n";
contenedor.setLayout(null);
contenedor.add(comboOpcionesRecta);
contenedor.add(radioMod);
contenedor.add(radioArista);
contenedor.add(radioNodo);
contenedor.add(ayudaCombo);
contenedor.add(lienzo);
contenedor.add(aplicar);
contenedor.add(panel);
contenedor.add(nuevo);
contenedor.add(recuperar);
contenedor.add(ayuda);
contenedor.add(titulo);
frame.setFont(font);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(1000, 600);
frame.setLocation(10, 20);
frame.setTitle("GrafoMatic Displayer");
frame.setVisible(true);
lienzo.addMouseListener(this);
lienzo.addMouseMotionListener(this);
aplicar.addActionListener(this);
nuevo.addActionListener(this);
recuperar.addActionListener(this);
radioNodo.addItemListener(this);
radioArista.addItemListener(this);
radioMod.addItemListener(this);
ayudaCombo.addItemListener(this);
}
public void mouseClicked(MouseEvent evento)
{
if (evento.getClickCount() ==
2&&radioNodo.isSelected()==true)
{
String nombre = "hay";
do
{
try

{
nombre =
JOptionPane.showInputDialog(null,"Ingrese la Etiqueta del Nodo");
nombre.length();
}
catch(NullPointerException e)
{
return;
}
if(grafo.getNombres().contains(nombre)||nombre==null)
{
JOptionPane.showMessageDialog(null,"La Etiqueta es incorrecta, recuerde
que no debe haber otra igual","Ingrese de nuevo la
Etiqueta",JOptionPane.ERROR_MESSAGE );
nombre="hay";
}
}
while(nombre=="hay");
Punto punto = new Punto((int)
evento.getPoint().getX() - 5, (int) evento.getPoint().getY() - 5,
nombre);
grafo.ingresarNodo(nombre);
punto.pintarPunto(lienzo.getGraphics());
puntos.add(punto);
lienzo.setPuntos(puntos);
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==aplicar)
{
AlgoritmoKruskal nuevo=new AlgoritmoKruskal();
Grafo kruskal= new Grafo();
kruskal=nuevo.aplicarKruskal(grafo);
lienzo.cambiarGrafo(kruskal);
}
if(e.getSource()==nuevo)
{
grafo=new Grafo();
lienzo.getAristas().clear();
lienzo.getPuntos().clear();
lienzo.getNeo().clear();
aristas.clear();
lienzo.punto=false;
lienzo.repaint();
}
if(e.getSource()==recuperar)
{
for(int i=0;i<lienzo.getNeo().size();i++)
{
Arista
arista=(Arista)lienzo.getNeo().get(i);

arista.setColor(new Color(0,128,128));
}
lienzo.getNeo().clear();
lienzo.estado=false;
lienzo.repaint();
}
}
public void itemStateChanged(ItemEvent evento)
{
if (evento.getSource() == radioNodo)
comboOpcionesRecta.setEnabled(false);
else
comboOpcionesRecta.setEnabled(true);
if(evento.getSource()==radioNodo||radioNodo.isSelected())
lienzo.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
else
lienzo.setCursor(Cursor.getDefaultCursor());
if(evento.getSource()==ayudaCombo)
{
if(ayudaCombo.getSelectedIndex()==0)
area.setText(ayudaNod);
if(ayudaCombo.getSelectedIndex()==1)
area.setText(ayudaAri);
if(ayudaCombo.getSelectedIndex()==2)
area.setText(ayudaMod);
if(ayudaCombo.getSelectedIndex()==3)
area.setText(ayudaNue);
if(ayudaCombo.getSelectedIndex()==4)
area.setText(ayudaApl);
if(ayudaCombo.getSelectedIndex()==5)
area.setText(ayudaRes);
}
}
public void mousePressed(MouseEvent arg0)
{
contador=0;
if(radioArista.isSelected())
{
for (int i = 0; i < puntos.size(); i++)
{
if
(puntos.get(i).ecuacionDeCirculo(arg0.getPoint()))
{
puntos.get(i).setColorPunto(Color.RED);//pintarPunto(lienzo.getGraphics()
, Color.RED);
x=puntos.get(i).getUbicacion().x;
y=puntos.get(i).getUbicacion().y;
if(comboOpcionesRecta.getSelectedIndex()==1)
{

pun[contador] =
puntos.get(i);
contador++;
}
pun[contador] = puntos.get(i);
break;
}
}
}
if(radioMod.isSelected())
{
for (int i = 0; i < puntos.size(); i++)
{
if
(puntos.get(i).ecuacionDeCirculo(arg0.getPoint()))
{
puntos.get(i).setColorPunto(Color.RED);
pun[contador] = puntos.get(i);
break;
}
}
contador=0;
}
lienzo.repaint();
}
public void mouseReleased(MouseEvent arg0)
{
if(radioArista.isSelected())
{
if(pun[1]==null||pun[1].ecuacionDeCirculo(arg0.getPoint())==false||pun[0]
.getUbicacion().equals(pun[1].getUbicacion()))
contador=0;
if(contador==2||comboOpcionesRecta.getSelectedIndex()==1)
{
float peso=-1;
do
{
try
{
peso =
Float.parseFloat(JOptionPane.showInputDialog(null,"Ingrese el Peso de la
Arista"));
}
catch(NumberFormatException ex)
{
JOptionPane.showMessageDialog(null,"El peso de la Arista debe ser un
Nmero","Ingrese de nuevo el Peso",JOptionPane.ERROR_MESSAGE );
peso=-1;

}
catch(NullPointerException e)
{
pun[0].setColorPunto(Color.BLUE);
if(pun[1]!=null)
pun[1].setColorPunto(Color.BLUE);
lienzo.punto=false;
lienzo.repaint();
return;
}
}
while(peso==-1);
Arista arista=new Arista(pun[0], pun[1],
comboOpcionesRecta.getSelectedIndex(),peso);
aristas.add(arista);
lienzo.setAristas(aristas);
arista.pintarRecta(lienzo.getGraphics());
grafo.adicionarEnlace(pun[0].getNombre(),pun[1].getNombre(),peso);
contador = 0;
pun[0].setColorPunto(Color.BLUE);
pun[1].setColorPunto(Color.BLUE);
lienzo.punto=false;
lienzo.repaint();
}
}
if(pun[0]!=null)
pun[0].setColorPunto(Color.BLUE);
lienzo.repaint();
lienzo.punto=false;
contador=0;
pun[0]=null;
pun[1]=null;
}
public void mouseEntered(MouseEvent arg0)
{
}
public void mouseExited(MouseEvent arg0)
{
}
public void mouseDragged(MouseEvent e) {

if(radioArista.isSelected())
{
for (int i = 0; i < puntos.size(); i++)
{
if
(puntos.get(i).ecuacionDeCirculo(e.getPoint()))
{
pun[1] = puntos.get(i);
pun[1].setColorPunto( Color.RED);
break;
}
else
if(pun[1]!=null&&pun[1]!=pun[0])
pun[1].setColorPunto(Color.BLUE);
}
if(pun[0]!=null)
{
lienzo.setA(new Point(x,y));
lienzo.setB(e.getPoint());
lienzo.punto=true;
lienzo.repaint();
}
contador=2;
}
if(radioMod.isSelected()&&pun[0]!=null)
{
Point ubicacion=new Point(e.getX()-5,e.getY()-5);
pun[0].setUbicacion(ubicacion);
lienzo.repaint();
}
}
public void mouseMoved(MouseEvent e) {
if(radioMod.isSelected())
{
for (int i = 0; i < puntos.size(); i++)
{
if
(puntos.get(i).ecuacionDeCirculo(e.getPoint()))
puntos.get(i).pintarPunto(lienzo.getGraphics(), Color.RED);
else
puntos.get(i).pintarPunto(lienzo.getGraphics(), Color.BLUE);
}
}
}
public Grafo getGrafo()
{
return grafo;

}
}

Clase Aplicacin[editar]
// Esta clase es la principal y es la que permite ver corriendo el
programa.
public class Aplicacion {
public static void main(String args[])
{
Ventana mi=new Ventana();
mi.area.setEditable(false);
}
}

Modo de compilacin y ejecucin[editar]


Para poder compilar y ejecutar el programa debe tener instalado en su computador el jdk de
java 1.5 o mejores actualizaciones y adems debe tener el path de Windows configurado
con el jdk. Ms sobre configuracin del path
Antes de comenzar tiene que copiar cada una de las clases en un bloc de notas separado y
guardarlo con el mismo nombre de la clase y con extensin .java. Por ejemplo: al copiar la
clase AlgoritmoKruskal en un bloc de notas la guarda como AlgoritmoKruskal.java.
Para compilar abra la consola, o para Windows XP la herramienta smbolo del sistema,
estando all dirjase al directorio donde tiene todas las clases guardadas (Todas las clases
deben estar en el mismo directorio para que el programa corra correctamente) y enseguida
copie el siguiente comando javac Aplicacion.java, esto le dice a java que compile el
main del programa que se encuentra en Aplicacion.java. Si hace esto correctamente
deben haberse creado en el directorio de las clases varios archivos .class, uno para cada
clase y con el mismo nombre de la clase.
Para ejecutar tiene que haber compilado primero. Nuevamente abra la consola, o smbolo
del sistema, y dirjase al directorio donde se encuentran todas las clases y digite el siguiente
comando java Aplicacion, esto le dice a java que ejecute el main del programa. Si lo
hace correctamente el programa debe estar corriendo.

Pruebas[editar]

En este primer grafo podemos ver que el


algoritmo ha seleccionado las aristas con
menor peso que son las de 9 y 10.

El algoritmo hace una seleccin de la


menor arista del grafo y la aade a un
rbol de manera que al aadirla al rbol
no forme un ciclo.
En este ejemplo el rbol que es creado por
el algoritmo es el representado por las
lneas rojas en la figura b).

En este segundo ejemplo podemos observar


que decisin toma el algoritmo en caso que
haya varias aristas con el mismo peso.

El algoritmo sigue el mismo criterio, hace


una seleccin de la menor arista del grafo
y la aade a un rbol de manera que al
aadirla al rbol no forme un ciclo.
En este ejemplo podemos ver claramente
el criterio del que se habla. El algoritmo
aadira al rbol la arista con peso 4,
luego la arista con peso 5, luego la que
tiene peso 7 y al momento de aadir la
arista de peso 8 se da cuenta que si aade
la arista e-d forma un ciclo y la desechara
y tomara luego a a-c, como esta no forma
ciclo entonces la aade al rbol.
Para la implementacin de este algoritmo
tambin influye el orden en el cual el
usuario dibujo las aristas por que el
algoritmo pudo haber seleccionado la
arista a-c primero, esto lo veremos ms
claro en el siguiente ejemplo.

El algoritmo sigue el mismo criterio, hace una


seleccin de la menor arista del grafo y la
aade a un rbol de manera que al aadirla al
rbol no forme un ciclo.

El algoritmo toma en orden ascendente las


aristas pero tambin tiene en cuenta el
orden en el cual, el usuario, dibujo las
aristas. Para este caso el usuario dibujo
primero la arista b-d y luego la c-d,
debido a esto el rbol que da como
resultado no me toma la arista c-d por que
formara un ciclo en el rbol.

Tiempo empleado[editar]
Para una implementacin ptima del algoritmo haciendo uso de una interfaz grafica y una
estructura adicional se hicieron necesarias alrededor de 15 horas, incluyendo el tiempo que
se necesit para investigar y complementar los conceptos necesarios para lograr el resultado
obtenido y deseado.

Tiempo de Ejecucin T(n)[editar]


Sea T(n) el nmero de nodos que posee el grafo. Dado que se trata de un grafo denso
podemos afirmar que la longitud del camino mximo ser n. Igualmente cada llamada
recursiva supondr una disminucin del problema en exactamente la unidad. De forma
similar, puede afirmarse que el nmero de llamadas recursivas ir disminuyendo en uno
puesto que en cada nivel hay un nodo adyacente ms que ya ha sido visitado. Por ltimo
puede observarse que dentro del ciclo se realizan al menos n comparaciones. Con los
hechos nombrados con anterioridad es posible establecer la siguiente relacin de
recurrencia: T(n) = (n-1) T(n-1) + n Siendo esta recurrencia no homognea, es decir, en este
caso la combinacin lineal no es igual a cero, tal como puede verse en la siguiente
expresin: A0tn +a1tn-1 +..+ aktn-k = bnp(n)
Se procede ahora a definir el valor de b=2 y p(n)=n Obteniendo que el polinomio
caracterstico es:
(x-(n-1)) (x-1) con races (n-1) (de multiplicidad 1) y 1 (de multiplicidad 2).
Por lo tanto todas las soluciones son de la forma tn= c1(n-1)n +c21n+c3n1n
Siempre y cuando t0 >=0 para todo n, se concluye inmediatamente que t pertenece a O (n1)n

Conclusiones[editar]

El algoritmo de kruskal es sencillo de implementar con las herramientas adecuadas.

El algoritmo de kruskal, al momento de implementarlo en algn lenguaje de


programacin, no es tan ptimo con respecto a otros algoritmos que cumplen el mismo
objetivo, como el de Prim, debido que al momento de implementarlo se tiene la limitante
de disear un algoritmo adicional que encuentre ciclos que en este caso no es el ms
ptimo.

Al momento de implementar el algoritmo es ms ptimo ordenar a medida que el usuario


ingresa aristas que ordenar despus de terminado el grafo. Tambin sera bueno aadir las
aristas en una cola de prioridad, ya que se evita igualmente la bsqueda de la arista
menor.

Das könnte Ihnen auch gefallen