95 lines
3.7 KiB
Markdown
95 lines
3.7 KiB
Markdown
|
---
|
||
|
title: Dijkstra's Algorithm
|
||
|
localeTitle: El algoritmo de Dijkstra
|
||
|
---
|
||
|
# El algoritmo de Dijkstra
|
||
|
|
||
|
El algoritmo de Dijkstra es un algoritmo gráfico presentado por EW Dijkstra. Encuentra la ruta más corta de una sola fuente en un gráfico con bordes no negativos (¿por qué?)
|
||
|
|
||
|
Creamos 2 matrices: visitada y distancia, que registran si un vértice es visitado y cuál es la distancia mínima desde el vértice de origen respectivamente. La matriz inicialmente visitada se asigna como falsa y la distancia como infinita.
|
||
|
|
||
|
Partimos del vértice fuente. Deje que el vértice actual sea u y sus vértices adyacentes sean v. Ahora, para cada v adyacente a u, la distancia se actualiza si no se ha visitado antes y la distancia desde u es menor que su distancia actual. Luego seleccionamos el siguiente vértice con la menor distancia y que no ha sido visitado.
|
||
|
|
||
|
La cola de prioridad se usa a menudo para cumplir con este último requisito en el menor tiempo posible. A continuación se muestra una implementación de la misma idea utilizando la cola de prioridad en Java.
|
||
|
|
||
|
```java
|
||
|
import java.util.*;
|
||
|
public class Dijkstra {
|
||
|
class Graph {
|
||
|
LinkedList<Pair<Integer>> adj[];
|
||
|
int n; // Number of vertices.
|
||
|
Graph(int n) {
|
||
|
this.n = n;
|
||
|
adj = new LinkedList[n];
|
||
|
for(int i = 0;i<n;i++) adj[i] = new LinkedList<>();
|
||
|
}
|
||
|
// add a directed edge between vertices a and b with cost as weight
|
||
|
public void addEdgeDirected(int a, int b, int cost) {
|
||
|
adj[a].add(new Pair(b, cost));
|
||
|
}
|
||
|
public void addEdgeUndirected(int a, int b, int cost) {
|
||
|
addEdgeDirected(a, b, cost);
|
||
|
addEdgeDirected(b, a, cost);
|
||
|
}
|
||
|
}
|
||
|
class Pair<E> {
|
||
|
E first;
|
||
|
E second;
|
||
|
Pair(E f, E s) {
|
||
|
first = f;
|
||
|
second = s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Comparator to sort Pairs in Priority Queue
|
||
|
class PairComparator implements Comparator<Pair<Integer>> {
|
||
|
public int compare(Pair<Integer> a, Pair<Integer> b) {
|
||
|
return a.second - b.second;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Calculates shortest path to each vertex from source and returns the distance
|
||
|
public int[] dijkstra(Graph g, int src) {
|
||
|
int distance[] = new int[gn]; // shortest distance of each vertex from src
|
||
|
boolean visited[] = new boolean[gn]; // vertex is visited or not
|
||
|
Arrays.fill(distance, Integer.MAX_VALUE);
|
||
|
Arrays.fill(visited, false);
|
||
|
PriorityQueue<Pair<Integer>> pq = new PriorityQueue<>(100, new PairComparator());
|
||
|
pq.add(new Pair<Integer>(src, 0));
|
||
|
distance[src] = 0;
|
||
|
while(!pq.isEmpty()) {
|
||
|
Pair<Integer> x = pq.remove(); // Extract vertex with shortest distance from src
|
||
|
int u = x.first;
|
||
|
visited[u] = true;
|
||
|
Iterator<Pair<Integer>> iter = g.adj[u].listIterator();
|
||
|
// Iterate over neighbours of u and update their distances
|
||
|
while(iter.hasNext()) {
|
||
|
Pair<Integer> y = iter.next();
|
||
|
int v = y.first;
|
||
|
int weight = y.second;
|
||
|
// Check if vertex v is not visited
|
||
|
// If new path through u offers less cost then update distance array and add to pq
|
||
|
if(!visited[v] && distance[u]+weight<distance[v]) {
|
||
|
distance[v] = distance[u]+weight;
|
||
|
pq.add(new Pair(v, distance[v]));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return distance;
|
||
|
}
|
||
|
|
||
|
public static void main(String args[]) {
|
||
|
Dijkstra d = new Dijkstra();
|
||
|
Dijkstra.Graph g = d.new Graph(4);
|
||
|
g.addEdgeUndirected(0, 1, 2);
|
||
|
g.addEdgeUndirected(1, 2, 1);
|
||
|
g.addEdgeUndirected(0, 3, 6);
|
||
|
g.addEdgeUndirected(2, 3, 1);
|
||
|
g.addEdgeUndirected(1, 3, 3);
|
||
|
|
||
|
int dist[] = d.dijkstra(g, 0);
|
||
|
System.out.println(Arrays.toString(dist));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
```
|