mirror of
https://github.com/Steffo99/appunti-magistrali.git
synced 2024-11-22 10:44:17 +00:00
3 KiB
3 KiB
Algoritmo di Dijkstra
L'Algoritmo di Dijkstra è un algoritmo che risolve il problema del percorso più breve da una sorgente singola per grafi con pesi reali positivi \mathbb{R}^+
.
L'algoritmo trova tutti i percorsi più brevi per raggiungere qualsiasi nodo del grafo partendo da un dato nodo, assieme al costo richiesto per farlo.
Funzionamento
- Separiamo tutti i nodi del grafo in due gruppi: visitati e non visitati.
- Tutti i nodi partono da non visitati.
- Per ogni nodo, manteniamo un valore "costo richiesto per raggiungerlo", che verrà cambiato man mano che l'algoritmo avanza.
- Il costo di partenza è
+∞
. - Il costo sarà definitivo per i nodi visitati, e provvisorio per i non visitati.
- Il costo di partenza è
- Creiamo un insieme detto frontiera che conterrà tutti i nodi non visitati adiacenti a quelli visitati.
- Prendiamo il nodo iniziale, che avrà un costo di
0
, e definiamolo il nodo attuale. - Finchè ci sono dei nodi non sono stati visitati, ripetiamo il seguente ciclo:
- Aggiungiamo i nodi adiacenti al nodo attuale alla frontiera.
- Il costo per raggiungerli sarà il costo per il nodo attuale sommato al costo dell'arco che li connette al nodo attuale.
Se questo costo risulta essere minore del costo provvisorio precedente, esso diventerà il nuovo costo. - Questa operazione è detta rilassamento dell'arco.
- Il costo per raggiungerli sarà il costo per il nodo attuale sommato al costo dell'arco che li connette al nodo attuale.
- Facciamo diventare visitato il nodo attuale.
- Il percorso che abbiamo fatto per raggiungerlo è obbligatoriamente il più breve.
- Il prossimo nodo attuale sarà il nodo di frontiera con un costo più basso.
- Per questo, è possibile definire l'algoritmo di Dijkstra come un algoritmo greedy.
- Aggiungiamo i nodi adiacenti al nodo attuale alla frontiera.
Non funziona se...
L'algoritmo smette di funzionare nel caso in cui siano presenti costi negativi e il grafo non sia aciclico, in quanto non saremmo mai in grado di rendere visitato un nodo.
Costo computazionale
Categoria | Upper bound |
---|---|
Tempo | O(nodi + archi) log nodi) |
Scomposizione
- Inizializzazione:
O(nodi)
- Creazione coda priorità:
O(nodi log nodi)
- Ciclo:
O((nodi + archi) log nodi)
Pseudocodice
import math
class Info:
def __init__(self, distance=math.inf, previous=None):
self.distance = distance
self.previous = previous
def dijkstra(graph, start):
data = [Info() for node in graph.nodes]
queue = PriorityQueue([start])
while queue:
node = queue.pop()
for arc in node.connections:
other = arc.other(node)
if data[node.number].distance + arc.cost < data[other].distance:
data[other].distance = data[node.number].distance + arc.cost
queue.decrease_priority_for(other, data[other].distance)
data[v].previous = node
return data