Está en la página 1de 19

Tecnológico Nacional de México; Tecnológico de Oaxaca

Facultad de Sistemas computacionales

Grafos implementación:
ESTRUCTURA DE DATOS - 3SC
Profesora: DALIA SILVA MARTINEZ
Fecha de entrega: 12 de diciembre de 2023

Nivel Intermedio: Estructuras de datos y Algoritmos

Arturo ortiz Rodríguez


[21161603]
[arturoortizrodriguezar@gmail.com]

Francisco I. Madero, Oaxaca de Juárez, Oax.


Introducción:
El proyecto de Grafos en Java busca implementar estructuras y algoritmos para modelar y
analizar relaciones entre entidades mediante la teoría de grafos. Utilizando programación
orientada a objetos, se construirá una representación eficiente de grafos y se implementarán
algoritmos fundamentales, abriendo la puerta a aplicaciones prácticas en redes sociales, rutas
óptimas, y otros escenarios donde las conexiones y relaciones son esenciales. Este proyecto
proporcionará una base sólida para comprender y aplicar conceptos clave de la teoría de grafos
en un entorno de programación Java.
En el contexto de la teoría de grafos, un grafo es una estructura de datos que consiste en un
conjunto de nodos (vértices) y un conjunto de aristas que conectan pares de nodos. Los grafos
pueden ser dirigidos o no dirigidos, dependiendo de si las aristas tienen dirección o no.

Para representar grafos en Java, hay varias formas comunes de hacerlo. Una de las
representaciones más utilizadas es la Lista de Adyacencia, que es especialmente útil para grafos
dispersos. Aquí hay un ejemplo simple de cómo puedes implementar un grafo no dirigido
utilizando una lista de adyacencia en Java:

import java.util.*;

class Grafo {
private Map<Integer, List<Arista>> listaAdyacencia;

public Grafo() {
listaAdyacencia = new HashMap<>();
}

public void agregarVertice(int vertice) {


listaAdyacencia.put(vertice, new ArrayList<>());
}

public void agregarArista(int verticeOrigen, int verticeDestino, int peso) {


listaAdyacencia.get(verticeOrigen).add(new Arista(verticeDestino, peso));
listaAdyacencia.get(verticeDestino).add(new Arista(verticeOrigen, peso));
}

public List<Arista> obtenerVecinos(int vertice) {


return listaAdyacencia.get(vertice);
}

public Map<Integer, Integer> dijkstra(int inicio) {


Map<Integer, Integer> distancias = new HashMap<>();
PriorityQueue<Nodo> colaPrioridad = new
PriorityQueue<>(Comparator.comparingInt(distancias::get));
// Inicializar distancias con infinito
for (int vertice : listaAdyacencia.keySet()) {
distancias.put(vertice, Integer.MAX_VALUE);
}

// Iniciar desde el nodo de inicio con distancia 0


distancias.put(inicio, 0);
colaPrioridad.add(new Nodo(inicio, 0));

while (!colaPrioridad.isEmpty()) {
int nodoActual = colaPrioridad.poll().vertice;

for (Arista vecino : listaAdyacencia.get(nodoActual)) {


int nuevaDistancia = distancias.get(nodoActual) + vecino.peso;
if (nuevaDistancia < distancias.get(vecino.destino)) {
distancias.put(vecino.destino, nuevaDistancia);
colaPrioridad.add(new Nodo(vecino.destino, nuevaDistancia));
}
}
}

return distancias;
}

static class Arista {


int destino;
int peso;

public Arista(int destino, int peso) {


this.destino = destino;
this.peso = peso;
}
}
static class Nodo {
int vertice;
int distancia;

public Nodo(int vertice, int distancia) {


this.vertice = vertice;
this.distancia = distancia;
}
}
}

public class Main2 {


public static void main(String[] args) {
Grafo grafo = new Grafo();

// Agregar vértices
grafo.agregarVertice(1);
grafo.agregarVertice(2);
grafo.agregarVertice(3);

// Agregar aristas con pesos


grafo.agregarArista(1, 2, 2);
grafo.agregarArista(2, 3, 1);

// Calcular caminos más cortos desde el nodo 1


Map<Integer, Integer> distancias = grafo.dijkstra(1);

// Imprimir las distancias


System.out.println("Distancias desde el nodo 1:");
for (Map.Entry<Integer, Integer> entry : distancias.entrySet()) {
System.out.println("Hacia " + entry.getKey() + ": " + entry.getValue());
}
}
}
1. import java.util.*;: Importa todas las clases del paquete java.util, que incluye las clases
necesarias para utilizar colecciones como List, ArrayList, HashMap, PriorityQueue, entre
otras.
2. class Grafo {: Declaración de la clase Grafo, que representa un grafo.
3. private Map<Integer, List<Arista>> listaAdyacencia;: Un mapa que representa la lista
de adyacencia del grafo. Cada vértice tiene una lista de aristas que conectan a sus
vecinos.
4. public Grafo() { listaAdyacencia = new HashMap<>(); }: Constructor de la clase Grafo
que inicializa la lista de adyacencia como un nuevo HashMap.
5. public void agregarVertice(int vertice) { listaAdyacencia.put(vertice, new
ArrayList<>()); }: Método para agregar un vértice al grafo. Crea una nueva entrada en el
mapa con la clave del vértice y una lista vacía de aristas.
6. public void agregarArista(int verticeOrigen, int verticeDestino, int peso) { ... }: Método
para agregar una arista entre dos vértices con un peso dado.
7. listaAdyacencia.get(verticeOrigen).add(new Arista(verticeDestino, peso));: Agrega
una nueva arista al vértice de origen en la lista de adyacencia.
8. listaAdyacencia.get(verticeDestino).add(new Arista(verticeOrigen, peso));: Agrega la
misma arista al vértice de destino (grafo no dirigido).
9. public List<Arista> obtenerVecinos(int vertice) { return
listaAdyacencia.get(vertice); }: Método para obtener la lista de aristas conectadas a un
vértice específico.
10. public Map<Integer, Integer> dijkstra(int inicio) { ... }: Método que implementa el
algoritmo de Dijkstra para encontrar las distancias mínimas desde un nodo de inicio a
todos los demás nodos.
11. Map<Integer, Integer> distancias = new HashMap<>();: Un mapa para almacenar las
distancias mínimas durante la ejecución del algoritmo de Dijkstra.
12. PriorityQueue<Nodo> colaPrioridad = new
PriorityQueue<>(Comparator.comparingInt(distancias::get));: Una cola de prioridad
que ordena los nodos según sus distancias mínimas, utilizando el comparador
proporcionado.
13. for (int vertice : listaAdyacencia.keySet()) { distancias.put(vertice,
Integer.MAX_VALUE); }: Inicializa las distancias de todos los nodos a infinito.
14. distancias.put(inicio, 0);: Inicializa la distancia del nodo de inicio a 0.
15. colaPrioridad.add(new Nodo(inicio, 0));: Añade el nodo de inicio a la cola de prioridad
con una distancia de 0.
16. while (!colaPrioridad.isEmpty()) { ... }: Inicia un bucle principal para explorar los nodos.
17. int nodoActual = colaPrioridad.poll().vertice;: Obtiene y elimina el nodo de menor
distancia de la cola de prioridad.
18. for (Arista vecino : listaAdyacencia.get(nodoActual)) { ... }: Itera sobre las aristas del
nodo actual.
19. int nuevaDistancia = distancias.get(nodoActual) + vecino.peso;: Calcula la nueva
distancia tentativa desde el nodo de inicio hasta el destino de la arista.
20. if (nuevaDistancia < distancias.get(vecino.destino)) { ... }: Verifica si la nueva distancia
es menor que la distancia actual almacenada para el destino de la arista.
21. distancias.put(vecino.destino, nuevaDistancia);: Actualiza la distancia del destino de la
arista en el mapa.
22. colaPrioridad.add(new Nodo(vecino.destino, nuevaDistancia));: Añade el destino de la
arista a la cola de prioridad con la nueva distancia.
23. static class Arista { ... }: Declaración de la clase interna Arista, que representa una arista
en el grafo.
24. int destino; int peso;: Variables que almacenan el destino y el peso de la arista.
25. public Arista(int destino, int peso) { ... }: Constructor de la clase Arista que inicializa la
arista con destino y peso.
26. static class Nodo { ... }: Declaración de la clase interna Nodo, que representa un nodo en
el grafo.
27. int vertice; int distancia;: Variables que almacenan el vértice y la distancia del nodo.
28. public Nodo(int vertice, int distancia) { ... }: Constructor de la clase Nodo que inicializa
el nodo con vértice y distancia.
29. public class Main2 { ... }: Declaración de la clase principal que contiene el método main
para probar el grafo y el algoritmo de Dijkstra.
30. Grafo grafo = new Grafo();: Crea una instancia de la clase Grafo.
31. grafo.agregarVertice(1); grafo.agregarVertice(2); grafo.agregarVertice(3);: Agrega
vértices al grafo.
32. grafo.agregarArista(1, 2, 2); grafo.agregarArista(2, 3, 1);: Agrega aristas entre los
vértices con pesos específicos.
33. Map<Integer, Integer> distancias = grafo.dijkstra(1);: Calcula las distancias más cortas
desde el nodo 1 utilizando Dijkstra.
34. for (Map.Entry<Integer, Integer> entry : distancias.entrySet()) { ... }: Itera sobre el mapa
de distancias y muestra los resultados.

En este ejemplo, la clase Grafo tiene un mapa donde las claves son los vértices y los valores son
listas de sus vecinos. Los métodos agregarVertice, agregarArista, y obtenerVecinos proporcionan
funciones básicas para trabajar con el grafo.

Esta es solo una de las muchas maneras de representar grafos en Java. La elección de la
estructura de datos depende de la naturaleza y requisitos específicos de tu aplicación. Otras
representaciones comunes incluyen la Matriz de Adyacencia y la Lista de Adyacencia con Nodos
y Aristas. Cada enfoque tiene sus ventajas y desventajas en términos de eficiencia y uso de
memoria.

Lista de Adyacencia con Nodos y Aristas en Java:


import java.util.*;

// Clase que representa un nodo en el grafo


class Nodo {
int valor; // Valor del nodo
List<Arista> aristas; // Lista de aristas conectadas al nodo

// Constructor que inicializa el nodo con un valor y una lista vacía de aristas
public Nodo(int valor) {
this.valor = valor;
this.aristas = new ArrayList<>();
}

// Método para agregar una arista conectada a este nodo


public void agregarArista(Nodo destino, int peso) {
Arista nuevaArista = new Arista(this, destino, peso);
aristas.add(nuevaArista);
}

// Sobrescritura del método toString para imprimir el valor del nodo


@Override
public String toString() {
return String.valueOf(valor);
}
}

// Clase que representa una arista en el grafo


class Arista {
Nodo origen; // Nodo de origen de la arista
Nodo destino; // Nodo de destino de la arista
int peso; // Peso de la arista

// Constructor que inicializa la arista con nodos de origen y destino, y un peso


public Arista(Nodo origen, Nodo destino, int peso) {
this.origen = origen;
this.destino = destino;
this.peso = peso;
}
}

// Clase principal que representa el grafo


class Grafo {
List<Nodo> nodos; // Lista de nodos en el grafo

// Constructor que inicializa la lista de nodos vacía


public Grafo() {
this.nodos = new ArrayList<>();
}

// Método para agregar un nodo al grafo


public void agregarNodo(int valor) {
nodos.add(new Nodo(valor));
}

// Método para agregar una arista entre dos nodos con un peso dado
public void agregarArista(int valorOrigen, int valorDestino, int peso) {
Nodo nodoOrigen = buscarNodo(valorOrigen);
Nodo nodoDestino = buscarNodo(valorDestino);

// Verificar si ambos nodos existen en el grafo


if (nodoOrigen != null && nodoDestino != null) {
// Agregar aristas tanto al nodo de origen como al nodo de destino (grafo no dirigido)
nodoOrigen.agregarArista(nodoDestino, peso);
nodoDestino.agregarArista(nodoOrigen, peso);
}
}

// Método privado para buscar un nodo en la lista de nodos del grafo


private Nodo buscarNodo(int valor) {
for (Nodo nodo : nodos) {
if (nodo.valor == valor) {
return nodo;
}
}
return null; // Retorna null si el nodo no se encuentra
}

// Método para aplicar el algoritmo de Dijkstra desde un nodo de inicio


public Map<Integer, Integer> dijkstra(int inicio) {
Map<Integer, Integer> distancias = new HashMap<>();
PriorityQueue<NodoDistancia> colaPrioridad = new
PriorityQueue<>(Comparator.comparingInt(distancias::get));

// Inicializar distancias con infinito


for (Nodo nodo : nodos) {
distancias.put(nodo.valor, Integer.MAX_VALUE);
}

// Iniciar desde el nodo de inicio con distancia 0


distancias.put(inicio, 0);
colaPrioridad.add(new NodoDistancia(buscarNodo(inicio), 0));

while (!colaPrioridad.isEmpty()) {
Nodo nodoActual = colaPrioridad.poll().nodo;

for (Arista arista : nodoActual.aristas) {


int nuevaDistancia = distancias.get(nodoActual.valor) + arista.peso;
if (nuevaDistancia < distancias.get(arista.destino.valor)) {
distancias.put(arista.destino.valor, nuevaDistancia);
colaPrioridad.add(new NodoDistancia(arista.destino, nuevaDistancia));
}
}
}

return distancias;
}

// Clase interna para representar un nodo con su distancia para Dijkstra


static class NodoDistancia {
Nodo nodo;
int distancia;

public NodoDistancia(Nodo nodo, int distancia) {


this.nodo = nodo;
this.distancia = distancia;
}
}
}

// Clase principal que contiene el método main para probar el grafo


public class Main {
public static void main(String[] args) {
Grafo grafo = new Grafo(); // Crear una instancia de la clase Grafo

// Agregar nodos al grafo


grafo.agregarNodo(1);
grafo.agregarNodo(2);
grafo.agregarNodo(3);

// Agregar aristas entre los nodos con pesos específicos


grafo.agregarArista(1, 2, 3);
grafo.agregarArista(2, 3, 5);

// Calcular caminos más cortos desde el nodo 1 utilizando Dijkstra


Map<Integer, Integer> distancias = grafo.dijkstra(1);
// Imprimir las distancias
System.out.println("Distancias desde el nodo 1:");
for (Map.Entry<Integer, Integer> entry : distancias.entrySet()) {
System.out.println("Hacia " + entry.getKey() + ": " + entry.getValue());
}
}
}
1. import java.util.*;: Importa todas las clases del paquete java.util, que incluye las clases
necesarias para utilizar colecciones como List, ArrayList, HashMap, PriorityQueue, entre
otras.
2. class Nodo {: Declaración de la clase Nodo, que representa un nodo en el grafo.
3. int valor;: Variable que almacena el valor del nodo.
4. List<Arista> aristas;: Lista que almacena las aristas conectadas al nodo.
5. public Nodo(int valor) { ... }: Constructor de la clase Nodo que inicializa el nodo con un
valor y una lista vacía de aristas.
6. this.valor = valor;: Asigna el valor del parámetro al atributo valor del nodo.
7. this.aristas = new ArrayList<>();: Inicializa la lista de aristas como una nueva ArrayList.
8. public void agregarArista(Nodo destino, int peso) { ... }: Método para agregar una arista
conectada a este nodo.
9. Arista nuevaArista = new Arista(this, destino, peso);: Crea una nueva arista con el
nodo actual como origen, el nodo destino proporcionado y un peso dado.
10. aristas.add(nuevaArista);: Agrega la nueva arista a la lista de aristas del nodo.
11. @Override: Indica que se está sobrescribiendo un método.
12. public String toString() { return String.valueOf(valor); }: Sobrescritura del método
toString para imprimir el valor del nodo.
13. class Arista {: Declaración de la clase Arista, que representa una arista en el grafo.
14. Nodo origen; Nodo destino; int peso;: Variables que almacenan el nodo de origen, el
nodo de destino y el peso de la arista.
15. public Arista(Nodo origen, Nodo destino, int peso) { ... }: Constructor de la clase Arista
que inicializa la arista con nodos de origen y destino, y un peso.
16. this.origen = origen; this.destino = destino; this.peso = peso;: Asigna los valores
proporcionados a los atributos de la arista.
17. class Grafo {: Declaración de la clase Grafo, que representa el grafo.
18. List<Nodo> nodos;: Lista que almacena los nodos en el grafo.
19. public Grafo() { this.nodos = new ArrayList<>(); }: Constructor de la clase Grafo que
inicializa la lista de nodos vacía.
20. public void agregarNodo(int valor) { nodos.add(new Nodo(valor)); }: Método para
agregar un nodo al grafo. Crea un nuevo nodo con el valor proporcionado y lo agrega a la
lista de nodos.
21. public void agregarArista(int valorOrigen, int valorDestino, int peso) { ... }: Método
para agregar una arista entre dos nodos con un peso dado.
22. Nodo nodoOrigen = buscarNodo(valorOrigen);: Busca el nodo de origen en la lista de
nodos.
23. Nodo nodoDestino = buscarNodo(valorDestino);: Busca el nodo de destino en la lista
de nodos.
24. if (nodoOrigen != null && nodoDestino != null) { ... }: Verifica si ambos nodos existen en
el grafo.
25. nodoOrigen.agregarArista(nodoDestino, peso);: Agrega una arista al nodo de origen.
26. nodoDestino.agregarArista(nodoOrigen, peso);: Agrega la misma arista al nodo de
destino (grafo no dirigido).
27. private Nodo buscarNodo(int valor) { ... }: Método privado para buscar un nodo en la
lista de nodos del grafo.
28. for (Nodo nodo : nodos) { ... }: Itera sobre la lista de nodos.
29. if (nodo.valor == valor) { return nodo; }: Comprueba si el valor del nodo actual es igual al
valor buscado.
30. return null;: Retorna null si el nodo no se encuentra.
31. public Map<Integer, Integer> dijkstra(int inicio) { ... }: Método para aplicar el algoritmo
de Dijkstra desde un nodo de inicio.
32. Map<Integer, Integer> distancias = new HashMap<>();: Crea un mapa para almacenar
las distancias mínimas durante la ejecución del algoritmo de Dijkstra.
33. PriorityQueue<NodoDistancia> colaPrioridad = new
PriorityQueue<>(Comparator.comparingInt(distancias::get));: Una cola de prioridad
que ordena los nodos según sus distancias mínimas, utilizando el comparador
proporcionado.
34. for (Nodo nodo : nodos) { distancias.put(nodo.valor, Integer.MAX_VALUE); }:
Inicializa las distancias de todos los nodos a infinito.
35. distancias.put(inicio, 0);: Inicializa la distancia del nodo de inicio a 0.
36. colaPrioridad.add(new NodoDistancia(buscarNodo(inicio), 0));: Añade el nodo de inicio
a la cola de prioridad con una distancia de 0.
37. while (!colaPrioridad.isEmpty()) { ... }: Inicia un bucle principal para explorar los nodos.
38. Nodo nodoActual = colaPrioridad.poll().nodo;: Obtiene y elimina el nodo de menor
distancia de la cola de prioridad.
39. for (Arista arista : nodoActual.aristas) { ... }: Itera sobre las aristas del nodo actual.
40. int nuevaDistancia = distancias.get(nodoActual.valor) + arista.peso;: Calcula la nueva
distancia tentativa desde el nodo de inicio hasta el destino de la arista.
41. if (nuevaDistancia < distancias.get(arista.destino.valor)) { ... }: Verifica si la nueva
distancia es menor que la distancia actual almacenada para el destino de la arista.
42. distancias.put(arista.destino.valor, nuevaDistancia);: Actualiza la distancia del destino
de la arista en el mapa.
43. colaPrioridad.add(new NodoDistancia(arista.destino, nuevaDistancia));: Añade el
destino de la arista a la cola de prioridad con la nueva distancia.
44. static class NodoDistancia { ... }: Clase interna estática para representar un nodo con su
distancia para Dijkstra.
45. public class Main { ... }: Clase principal que contiene el método main para probar la
implementación del grafo y el algoritmo de Dijkstra.
46. Grafo grafo = new Grafo();: Crea una instancia de la clase Grafo.
47. grafo.agregarNodo(1); grafo.agregarNodo(2); grafo.agregarNodo(3);: Agrega nodos al
grafo.
48. grafo.agregarArista(1, 2, 3); grafo.agregarArista(2, 3, 5);: Agrega aristas entre los nodos
con pesos específicos.
49. Map<Integer, Integer> distancias = grafo.dijkstra(1);: Calcula las distancias más cortas
desde el nodo 1 utilizando Dijkstra.
50. for (Map.Entry<Integer, Integer> entry : distancias.entrySet()) { ... }: Itera sobre el mapa
de distancias y muestra los resultados.

En este ejemplo, la clase Nodo representa los vértices del grafo, la clase Arista representa las
conexiones entre los nodos, y la clase Grafo contiene una lista de nodos y métodos para agregar
nodos y aristas. Este ejemplo asume un grafo no dirigido.
import java.util.Arrays;
import java.util.PriorityQueue;

public class MatrizAdyacencia {

private int[][] matriz; // La matriz de adyacencia


private int numVertices; // Número de vértices en el grafo

// Constructor que inicializa la matriz de adyacencia para un número dado de vértices


public MatrizAdyacencia(int numVertices) {
this.numVertices = numVertices;
this.matriz = new int[numVertices][numVertices];

// Inicializar la matriz con Integer.MAX_VALUE (sin conexiones) excepto la diagonal


principal con 0s
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
if (i != j) {
matriz[i][j] = Integer.MAX_VALUE;
}
}
}
}

// Método para agregar una arista entre dos vértices con un peso dado
public void agregarArista(int origen, int destino, int peso) {
matriz[origen][destino] = peso;
matriz[destino][origen] = peso; // Para grafos no dirigidos
}

// Método para imprimir la matriz de adyacencia


public void imprimirMatriz() {
for (int i = 0; i < numVertices; i++) {
System.out.println(Arrays.toString(matriz[i]));
}
}

// Método para aplicar el algoritmo de Dijkstra desde un vértice de inicio


public int[] dijkstra(int inicio) {
int[] distancias = new int[numVertices];
Arrays.fill(distancias, Integer.MAX_VALUE);
distancias[inicio] = 0;

PriorityQueue<NodoDistancia> colaPrioridad = new PriorityQueue<>();


colaPrioridad.add(new NodoDistancia(inicio, 0));

while (!colaPrioridad.isEmpty()) {
NodoDistancia nodoActual = colaPrioridad.poll();
for (int vecino = 0; vecino < numVertices; vecino++) {
if (matriz[nodoActual.vertice][vecino] != Integer.MAX_VALUE) {
int nuevaDistancia = distancias[nodoActual.vertice] + matriz[nodoActual.vertice]
[vecino];
if (nuevaDistancia < distancias[vecino]) {
distancias[vecino] = nuevaDistancia;
colaPrioridad.add(new NodoDistancia(vecino, nuevaDistancia));
}
}
}
}

return distancias;
}

// Clase interna para representar un nodo con su distancia para Dijkstra


static class NodoDistancia implements Comparable<NodoDistancia> {
int vertice;
int distancia;

public NodoDistancia(int vertice, int distancia) {


this.vertice = vertice;
this.distancia = distancia;
}

@Override
public int compareTo(NodoDistancia otro) {
return Integer.compare(this.distancia, otro.distancia);
}
}

public static void main(String[] args) {


MatrizAdyacencia grafo = new MatrizAdyacencia(4);
// Agregar aristas al grafo
grafo.agregarArista(0, 1, 1);
grafo.agregarArista(0, 2, 1);
grafo.agregarArista(1, 2, 1);
grafo.agregarArista(2, 3, 1);

// Imprimir la matriz de adyacencia


System.out.println("Matriz de adyacencia:");
grafo.imprimirMatriz();

// Calcular caminos más cortos desde el vértice 0 utilizando Dijkstra


int[] distancias = grafo.dijkstra(0);

// Imprimir las distancias


System.out.println("\nDistancias desde el vértice 0:");
for (int i = 0; i < distancias.length; i++) {
System.out.println("Hacia " + i + ": " + distancias[i]);
}
}
}
Ahora, una explicación línea por línea:
1. import java.util.*;: Importa todas las clases del paquete java.util, que incluye las clases
necesarias para utilizar colecciones como Map, List, PriorityQueue, entre otras.
2. class Grafo {: Declaración de la clase Grafo, que representa un grafo ponderado no
dirigido.
3. private Map<Integer, List<Arista>> listaAdyacencia;: Declara un mapa que asocia cada
vértice con una lista de aristas conectadas a ese vértice. La clave es el identificador del
vértice (entero), y el valor es una lista de aristas.
4. public Grafo() { listaAdyacencia = new HashMap<>(); }: Constructor de la clase Grafo
que inicializa la lista de adyacencia como un nuevo HashMap.
5. public void agregarVertice(int vertice) { listaAdyacencia.put(vertice, new
ArrayList<>()); }: Método para agregar un vértice al grafo. Crea una nueva lista de
adyacencia vacía para el vértice especificado.
6. public void agregarArista(int verticeOrigen, int verticeDestino, int peso)
{ listaAdyacencia.get(verticeOrigen).add(new Arista(verticeDestino, peso));
listaAdyacencia.get(verticeDestino).add(new Arista(verticeOrigen, peso)); }: Método
para agregar una arista entre dos vértices con un peso dado. Añade una nueva arista a las
listas de adyacencia de ambos vértices.
7. public List<Arista> obtenerVecinos(int vertice) { return
listaAdyacencia.get(vertice); }: Método para obtener la lista de aristas adyacentes a un
vértice dado.
8. public Map<Integer, Integer> dijkstra(int inicio) { ... }: Método que implementa el
algoritmo de Dijkstra para encontrar los caminos más cortos desde un nodo de inicio.
Retorna un mapa que asocia cada vértice con su distancia mínima desde el nodo de inicio.
9. Map<Integer, Integer> distancias = new HashMap<>();: Crea un mapa para almacenar
las distancias mínimas durante la ejecución del algoritmo de Dijkstra.
10. PriorityQueue<Nodo> colaPrioridad = new
PriorityQueue<>(Comparator.comparingInt(distancias::get));: Una cola de prioridad
que ordena los nodos según sus distancias mínimas, utilizando el comparador
proporcionado.
11. for (int vertice : listaAdyacencia.keySet()) { distancias.put(vertice,
Integer.MAX_VALUE); }: Inicializa las distancias de todos los vértices a infinito.
12. distancias.put(inicio, 0);: Inicializa la distancia del nodo de inicio a 0.
13. colaPrioridad.add(new Nodo(inicio, 0));: Añade el nodo de inicio a la cola de prioridad
con una distancia de 0.
14. while (!colaPrioridad.isEmpty()) { ... }: Inicia un bucle principal para explorar los nodos.
15. int nodoActual = colaPrioridad.poll().vertice;: Obtiene y elimina el nodo de menor
distancia de la cola de prioridad.
16. for (Arista vecino : listaAdyacencia.get(nodoActual)) { ... }: Itera sobre los vecinos del
nodo actual.
17. int nuevaDistancia = distancias.get(nodoActual) + vecino.peso;: Calcula la nueva
distancia tentativa desde el nodo de inicio hasta el vecino a través del nodo actual.
18. if (nuevaDistancia < distancias.get(vecino.destino)) { ... }: Verifica si la nueva distancia
es menor que la distancia actual almacenada para el vecino.
19. distancias.put(vecino.destino, nuevaDistancia);: Actualiza la distancia del vecino en el
mapa.
20. colaPrioridad.add(new Nodo(vecino.destino, nuevaDistancia));: Añade el vecino a la
cola de prioridad con la nueva distancia.
21. static class Arista { ... }: Clase estática interna que representa una arista en el grafo.
Contiene el destino y el peso de la arista.
22. static class Nodo { ... }: Clase estática interna que representa un nodo en el contexto del
algoritmo de Dijkstra. Contiene el vértice y la distancia desde el nodo de inicio.
23. public class Main2 { ... }: Clase principal que contiene el método main para probar la
implementación del grafo y el algoritmo de Dijkstra.
24. Grafo grafo = new Grafo();: Crea una instancia de la clase Grafo.
25. grafo.agregarVertice(1); grafo.agregarVertice(2); grafo.agregarVertice(3);: Agrega
vértices al grafo.
26. grafo.agregarArista(1, 2, 2); grafo.agregarArista(2, 3, 1);: Agrega aristas con pesos al
grafo.
27. Map<Integer, Integer> distancias = grafo.dijkstra(1);: Calcula las distancias más cortas
desde el nodo 1 utilizando Dijkstra.
28. for (Map.Entry<Integer, Integer> entry : distancias.entrySet()) { ... }: Itera sobre el mapa
de distancias y muestra los resultados.

Conclusión:
1. Representación de Grafos:
 Se proporcionaron ejemplos de dos enfoques comunes para representar grafos:
mediante listas de adyacencia y matrices de adyacencia.
 La representación mediante listas de adyacencia es más eficiente para grafos
dispersos, mientras que las matrices de adyacencia son útiles para grafos densos.
2. Implementación del Algoritmo de Dijkstra:
 Se incorporó el algoritmo de Dijkstra en dos implementaciones distintas, una para la
representación mediante listas de adyacencia y otra para la representación
mediante una matriz de adyacencia.
 La implementación a través de listas de adyacencia aprovecha las clases internas
para modelar nodos y aristas, y utiliza una cola de prioridad para optimizar la
búsqueda de las distancias mínimas.
3. Uso Práctico:
 Se proporcionaron ejemplos de cómo agregar vértices, aristas y calcular las
distancias más cortas utilizando el algoritmo de Dijkstra en diferentes tipos de
representaciones de grafos.
4. Consideraciones Generales:
 Se enfatizó la versatilidad de las representaciones de grafos y la importancia de
seleccionar la estructura adecuada según la naturaleza y características del grafo en
cuestión.
 La modularidad y la reutilización de código se promovieron mediante el uso de
clases y estructuras internas para modelar nodos y aristas.

También podría gustarte