Algoritmo de Dijkstra
¿Qué es el Algoritmo de Dijkstra?
El algoritmo de Dijkstra es una técnica ampliamente utilizada para encontrar el camino más corto entre un nodo de origen y todos los demás nodos en un grafo ponderado no dirigido. Utiliza una estructura de cola de prioridad para garantizar la eficiencia durante la búsqueda.
El Código
class PriorityQueue {
constructor() {
this.values = [];
}
enqueue(val, priority) {
this.values.push({ val, priority });
this.sort();
}
dequeue() {
return this.values.shift();
}
sort() {
this.values.sort((a, b) => a.priority - b.priority);
}
}
class Graph {
constructor() {
this.adjacencyList = {};
}
addVertex(vertex) {
if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];
}
addEdge(vertex1, vertex2, weight) {
this.adjacencyList[vertex1].push({ node: vertex2, weight });
this.adjacencyList[vertex2].push({ node: vertex1, weight });
}
dijkstra(start, finish) {
const nodes = new PriorityQueue();
const distances = {};
const previous = {};
let path = []; // to return at end
let smallest;
for (let vertex in this.adjacencyList) {
if (vertex === start) {
distances[vertex] = 0;
nodes.enqueue(vertex, 0);
} else {
distances[vertex] = Infinity;
nodes.enqueue(vertex, Infinity);
}
previous[vertex] = null;
}
while (nodes.values.length) {
smallest = nodes.dequeue().val;
if (smallest === finish) {
while (previous[smallest]) {
path.push(smallest);
smallest = previous[smallest];
}
break;
}
if (smallest || distances[smallest] !== Infinity) {
for (let neighbor in this.adjacencyList[smallest]) {
let nextNode = this.adjacencyList[smallest][neighbor];
let candidate = distances[smallest] + nextNode.weight;
let nextNeighbor = nextNode.node;
if (candidate < distances[nextNeighbor]) {
distances[nextNeighbor] = candidate;
previous[nextNeighbor] = smallest;
nodes.enqueue(nextNeighbor, candidate);
}
}
}
}
return path.concat(smallest).reverse();
}
}
// Ejemplo de uso
const graph = new Graph();
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");
graph.addVertex("E");
graph.addVertex("F");
graph.addEdge("A", "B", 4);
graph.addEdge("A", "C", 2);
graph.addEdge("B", "E", 3);
graph.addEdge("C", "D", 2);
graph.addEdge("C", "F", 4);
graph.addEdge("D", "E", 3);
graph.addEdge("D", "F", 1);
graph.addEdge("E", "F", 1);
console.log("Camino más corto de A a E:", graph.dijkstra("A", "E"));
Puntos Clave del Algoritmo
- Entrada: Un grafo ponderado, un nodo inicial y un nodo final.
- Salida: El camino más corto desde el nodo inicial hasta el nodo final.
-
Método:
- Utiliza una cola de prioridad para priorizar los nodos con menor distancia acumulada.
- Actualiza las distancias desde el nodo actual a sus vecinos.
- Registra el nodo previo para reconstruir el camino más corto.
- Complejidad:
- Tiempo: O(V + E log V), donde V es el número de vértices y E el número de aristas.
- Espacio: O(V + E) para almacenar el grafo y la cola de prioridad.
- Ventajas: Encuentra caminos más cortos en grafos ponderados de manera eficiente.
- Desventajas: No funciona correctamente con aristas de peso negativo (usar Bellman-Ford en ese caso).
Ejemplo de Ejecución
Grafo inicial:
- Vértices:
A, B, C, D, E, F
- Aristas:
A-B(4), A-C(2), B-E(3), C-D(2), C-F(4), D-E(3), D-F(1), E-F(1)
Camino más corto desde A
hasta E
:
- Inicio en
A
, distancias:{ A: 0, B: ∞, C: ∞, D: ∞, E: ∞, F: ∞ }
. - Selecciona
C
(menor distancia acumulada) y actualiza las distancias de sus vecinos. - Continúa visitando los nodos según la prioridad en la cola.
- Al llegar a
E
, reconstruye el camino:[A, C, D, E]
.
Resultado final: Camino más corto es [A, C, D, E]
con distancia total de 7
.
Información Adicional
El algoritmo de Dijkstra es esencial en redes, sistemas de navegación y análisis de rutas. Su implementación con una cola de prioridad lo hace eficiente para aplicaciones en grafos densos y es fundamental en algoritmos de optimización.