In questo articolo discuteremo di uno degli algoritmi del percorso più breve più comunemente conosciuti, ovvero l'algoritmo del percorso più breve di Dijkstra, sviluppato dallo scienziato informatico olandese Edsger W. Dijkstra nel 1956. Inoltre, faremo un'analisi della complessità per questo algoritmo e anche vedere come differisce dagli altri algoritmi del percorso più breve.
Tabella dei contenuti
- Algoritmo di Dijkstra
- Necessità dell'algoritmo di Dijkstra (scopo e casi d'uso)
- L’algoritmo di Dijkstra può funzionare sia su grafi diretti che su grafi non orientati?
- Algoritmo per l'algoritmo di Dijkstra
- Come funziona l’algoritmo di Dijkstra?
- Pseudo codice per l'algoritmo di Dijkstra
- Implementazione dell’algoritmo di Dijkstra:
- Algoritmi di Dijkstra vs algoritmo di Bellman-Ford
- Algoritmo di Dijkstra contro algoritmo di Floyd-Warshall
- Algoritmo di Dijkstra vs algoritmo A*
- Problemi pratici sull'algoritmo di Dijkstra
- Conclusione:

Algoritmo di Dijkstra:
Algoritmo di Dijkstra è un algoritmo popolare per risolvere molti problemi di percorso minimo a sorgente singola con peso del bordo non negativo nei grafici, ovvero trovare la distanza più breve tra due vertici su un grafico. È stato concepito da un informatico olandese Edsger W. Dijkstra nel 1956.
L'algoritmo mantiene un insieme di vertici visitati e un insieme di vertici non visitati. Inizia dal vertice di origine e seleziona iterativamente il vertice non visitato con la distanza provvisoria più piccola dalla sorgente. Quindi visita i vicini di questo vertice e aggiorna le loro distanze provvisorie se viene trovato un percorso più breve. Questo processo continua fino al raggiungimento del vertice di destinazione o fino alla visita di tutti i vertici raggiungibili.
Necessità dell'algoritmo di Dijkstra (scopo e casi d'uso)
La necessità dell’algoritmo di Dijkstra nasce in molte applicazioni in cui è fondamentale trovare il percorso più breve tra due punti.
Per esempio , Può essere utilizzato nei protocolli di routing per reti di computer e utilizzato anche dai sistemi cartografici per trovare il percorso più breve tra il punto di partenza e la Destinazione (come spiegato in Come funziona Google Maps? )
L’algoritmo di Dijkstra può funzionare sia su grafi diretti che su grafi non orientati?
SÌ , l'algoritmo di Dijkstra può funzionare sia su grafi diretti che su grafici non orientati poiché questo algoritmo è progettato per funzionare su qualsiasi tipo di grafico purché soddisfi i requisiti di avere pesi degli archi non negativi e di essere connesso.
- In un grafico diretto, ogni bordo ha una direzione, che indica la direzione del viaggio tra i vertici collegati dal bordo. In questo caso l'algoritmo segue la direzione dei bordi durante la ricerca del percorso più breve.
- In un grafico non orientato, i bordi non hanno direzione e l'algoritmo può spostarsi sia in avanti che all'indietro lungo i bordi durante la ricerca del percorso più breve.
Algoritmo per l'algoritmo di Dijkstra:
- Contrassegna il nodo sorgente con una distanza corrente pari a 0 e il resto con infinito.
- Imposta il nodo non visitato con la distanza corrente più piccola come nodo corrente.
- Per ogni vicino, N del nodo corrente aggiunge la distanza corrente del nodo adiacente con il peso del bordo che collega 0->1. Se è inferiore alla distanza corrente di Nodo, impostala come la nuova distanza corrente di N.
- Contrassegna il nodo corrente 1 come visitato.
- Andare al passaggio 2 se sono presenti nodi non visitati.
Come funziona l’algoritmo di Dijkstra?
Vediamo come funziona l'algoritmo di Dijkstra con un esempio riportato di seguito:
L’algoritmo di Dijkstra genererà il percorso più breve dal nodo 0 a tutti gli altri nodi nel grafico.
Considera il grafico seguente:
Algoritmo di Dijkstra
L'algoritmo genererà il percorso più breve dal nodo 0 a tutti gli altri nodi del grafico.
Per questo grafico assumeremo che il peso dei bordi rappresenti la distanza tra due nodi.
restituendo array in JavaCome possiamo vedere, abbiamo il percorso più breve da,
Dal nodo 0 al nodo 1, da
Dal nodo 0 al nodo 2, da
Dal nodo 0 al nodo 3, da
Dal nodo 0 al nodo 4, da
Dal nodo 0 al nodo 6.Inizialmente abbiamo una serie di risorse indicate di seguito:
- La distanza dal nodo di origine a se stesso è 0. In questo esempio il nodo di origine è 0.
- La distanza dal nodo sorgente a tutti gli altri nodi è sconosciuta, quindi li contrassegniamo tutti come infinito.
Esempio: 0 -> 0, 1-> ∞,2-> ∞,3-> ∞,4-> ∞,5-> ∞,6-> ∞.
- avremo anche una serie di elementi non visitati che terranno traccia dei nodi non visitati o non contrassegnati.
- L'algoritmo verrà completato quando tutti i nodi contrassegnati come visitati e la distanza tra loro verranno aggiunti al percorso. Nodi non visitati: - 0 1 2 3 4 5 6.
Passo 1: Inizia dal nodo 0 e contrassegna il nodo come visitato come puoi controllare nell'immagine qui sotto. Il nodo visitato è contrassegnato in rosso.
Algoritmo di Dijkstra
Passo 2: Controlla i nodi adiacenti, ora dobbiamo scegliere (scegli il nodo 1 con distanza 2 o scegli il nodo 2 con distanza 6) e scegli il nodo con distanza minima. In questo passaggio Nodo 1 è la distanza minima del nodo adiacente, quindi contrassegnalo come visitato e somma la distanza.
Distanza: Nodo 0 -> Nodo 1 = 2
Algoritmo di Dijkstra
Passaggio 3: Quindi vai avanti e controlla il nodo adiacente che è il nodo 3, quindi contrassegnalo come visitato e somma la distanza, ora la distanza sarà:
Distanza: Nodo 0 -> Nodo 1 -> Nodo 3 = 2 + 5 = 7
Algoritmo di Dijkstra
perché la stringa è immutabile in JavaPassaggio 4: Ancora una volta abbiamo due scelte per i nodi adiacenti (o possiamo scegliere il nodo 4 con distanza 10 oppure possiamo scegliere il nodo 5 con distanza 15), quindi scegliamo il nodo con distanza minima. In questo passaggio Nodo 4 è la distanza minima del nodo adiacente, quindi contrassegnalo come visitato e somma la distanza.
Distanza: Nodo 0 -> Nodo 1 -> Nodo 3 -> Nodo 4 = 2 + 5 + 10 = 17
Algoritmo di Dijkstra
Passaggio 5: Ancora una volta, vai avanti e controlla il nodo adiacente che lo è Nodo 6 , quindi contrassegnalo come visitato e somma la distanza, ora la distanza sarà:
Distanza: Nodo 0 -> Nodo 1 -> Nodo 3 -> Nodo 4 -> Nodo 6 = 2 + 5 + 10 + 2 = 19
Algoritmo di Dijkstra
Quindi, la distanza più breve dal vertice sorgente è 19, che è quella ottimale
formato stringa Java lungo
Pseudo codice per l'algoritmo di Dijkstra
funzione Dijkstra(Grafico, sorgente):
// Inizializza le distanze verso tutti i nodi come infinito e verso il nodo sorgente come 0.distanze = mappa(tutti i nodi -> infinito)
distanze = 0
// Inizializza un insieme vuoto di nodi visitati e una coda prioritaria per tenere traccia dei nodi da visitare.
visitato = insieme vuoto
coda = nuova PriorityQueue()
coda.enqueue(fonte, 0)// Ripete finché tutti i nodi non sono stati visitati.
mentre la coda non è vuota:
// Rimuove dalla coda il nodo con la distanza più piccola dalla coda con priorità.
corrente = coda.dequeue()// Se il nodo è già stato visitato, saltalo.
se attuale nel visitato:
Continua// Contrassegna il nodo come visitato.
visitato.add(corrente)// Controlla tutti i nodi vicini per vedere se le loro distanze devono essere aggiornate.
per il vicino in Graph.neighbors(current):
// Calcola la distanza provvisoria dal vicino attraverso il nodo corrente.
distanza_tentativa = distanze[corrente] + Graph.distanza(corrente, vicino)// Se la distanza provvisoria è inferiore alla distanza corrente dal vicino, aggiorna la distanza.
se distanza_provvisoria
distanze[vicino] = distanza_tentativa// Accoda il vicino con la sua nuova distanza affinché venga preso in considerazione per le visite future.
coda.enqueue(vicino, distanze[vicino])// Restituisce le distanze calcolate dalla sorgente a tutti gli altri nodi nel grafico.
distanze di ritorno
Implementazione dell’algoritmo di Dijkstra:
Esistono diversi modi per implementare l'algoritmo di Dijkstra, ma i più comuni sono:
- Coda prioritaria (implementazione basata su heap):
- Implementazione basata su array:
1. Algoritmo del percorso più breve di Dijkstra che utilizza priorità_queue (heap)
In questa implementazione, ci viene dato un grafico e un vertice sorgente nel grafico, trovando i percorsi più brevi dalla sorgente a tutti i vertici nel grafico dato.
Esempio:
Ingresso: Fonte = 0
Esempio
Produzione: Vertice
Distanza del vertice dalla sorgente
0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19
Di seguito è riportato l'algoritmo basato sull'idea di cui sopra:
- Inizializza i valori della distanza e la coda di priorità.
- Inserisci il nodo sorgente nella coda di priorità con distanza 0.
- Mentre la coda di priorità non è vuota:
- Estrai il nodo con la distanza minima dalla coda prioritaria.
- Aggiorna le distanze dei suoi vicini se viene trovato un percorso più breve.
- Inserisci i vicini aggiornati nella coda di priorità.
Di seguito è riportata l'implementazione C++ dell'approccio precedente:
C++ // Program to find Dijkstra's shortest path using // priority_queue in STL #include using namespace std; #define INF 0x3f3f3f3f // iPair ==>Coppia di numeri interi typedef coppia iPair; // Questa classe rappresenta un grafo diretto utilizzando // la rappresentazione della lista di adiacenza class Graph { int V; // Numero di vertici // In un grafico pesato, dobbiamo memorizzare il vertice // e la coppia di pesi per ogni lista di archi>* agg; pubblico: Graph(int V); // Costruttore // funzione per aggiungere un bordo al grafico void addEdge(int u, int v, int w); // stampa il percorso più breve da s void shortestPath(int s); }; // Alloca memoria per la lista di adiacenze Graph::Graph(int V) { this->V = V; agg = nuova lista [V]; } void Graph::addEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w)); adj[v].push_back(make_pair(u, w)); } // Stampa i percorsi più brevi da src a tutti gli altri vertici void Graph::shortestPath(int src) { // Crea una coda con priorità per memorizzare i vertici che // vengono preelaborati. Questa è una strana sintassi in C++. // Fare riferimento al collegamento seguente per i dettagli di questa sintassi // https://www.techcodeview.com priorità_queue , maggiore > pq; // Crea un vettore per le distanze e inizializza tutte // le distanze come vettore infinito (INF). dist(V,INF); // Inserisci la sorgente stessa nella coda di priorità e inizializza // la sua distanza come 0. pq.push(make_pair(0, src)); dist[origine] = 0; /* Ciclo finché la coda con priorità non diventa vuota (o tutte le distanze non sono finalizzate) */ while (!pq.empty()) { // Il primo vertice della coppia è il vertice della distanza minima //, estrailo dalla coda con priorità. // l'etichetta del vertice è memorizzata nel secondo della coppia (deve // essere fatto in questo modo per mantenere la distanza // ordinata dei vertici (la distanza deve essere il primo elemento // della coppia) int u = pq.top().second; pq.pop(); // 'i' viene utilizzato per ottenere tutti i vertici adiacenti di una // lista di vertici>::iteratore i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { // Ottieni l'etichetta del vertice e il peso della corrente // adiacente a u. int v = (*i).primo; int peso = (*i).secondo; // Se c'è un percorso in cortocircuito da v attraverso u. if (dist[v]> dist[u] + peso) { // Aggiornamento della distanza di v dist[v] = dist[u] + peso; pq.push(make_pair(dist[v], v)); } } } // Stampa le distanze più brevi memorizzate in dist[] printf('Vertex Distance from Source
'); for (int i = 0; i< V; ++i) printf('%d %d
', i, dist[i]); } // Driver program to test methods of graph class int main() { // create the graph given in above figure int V = 7; Graph g(V); // making above shown graph g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); return 0; }>
Giava import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.PriorityQueue; public class DijkstraAlgoForShortestDistance { static class Node implements Comparable{ in tv; distanza intera; public Node(int v, int distanza) { this.v = v; this.distanza = distanza; } @Override public int compareTo(Nodo n) { if (this.distance<= n.distance) { return -1; } else { return 1; } } } static int[] dijkstra( int V, ArrayList >> adj, int S) { boolean[] visitato = new boolean[V]; HashMap mappa = nuova HashMap(); PriorityQueueq = nuova PriorityQueue(); map.put(S, nuovo nodo(S, 0)); q.add(nuovo nodo(S, 0)); while (!q.isEmpty()) { Nodo n = q.poll(); int v = n.v; int distanza = n.distanza; visitato[v] = vero; Lista di array > listaadj = adj.get(v); per (ArrayList adjLink : adjList) { if (visited[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), nuovo nodo (v, distanza + adjLink.get(1))); } else { Nodo sn = map.get(adjLink.get(0)); if (distanza + adjLink.get(1)< sn.distance) { sn.v = v; sn.distance = distance + adjLink.get(1); } } q.add(new Node(adjLink.get(0), distance + adjLink.get(1))); } } } int[] result = new int[V]; for (int i = 0; i < V; i++) { result[i] = map.get(i).distance; } return result; } public static void main(String[] args) { ArrayList >> adj = new ArrayList(); HashMap >> mappa = new HashMap(); intero V = 6; intero E = 5; int[] u = { 0, 0, 1, 2, 4 }; int[] v = { 3, 5, 4, 5, 5 }; int[] w = { 9, 4, 4, 10, 3 }; for (int i = 0; i< E; i++) { ArrayList bordo = new ArrayList(); bordo.add(v[i]); bordo.add(w[i]); Lista di array > adjLista; if (!map.containsKey(u[i])) { adjList = new ArrayList(); } else { adjList = map.get(u[i]); } adjList.add(bordo); map.put(u[i], adjLista); Lista di array bordo2 = nuovo ArrayList(); bordo2.add(u[i]); bordo2.add(w[i]); Lista di array > adjLista2; if (!map.containsKey(v[i])) { adjList2 = new ArrayList(); } else { adjLista2 = map.get(v[i]); } adjLista2.add(bordo2); map.put(v[i], adjLista2); } for (int i = 0; i< V; i++) { if (map.containsKey(i)) { adj.add(map.get(i)); } else { adj.add(null); } } int S = 1; // Input sample //[0 [[3, 9], [5, 4]], // 1 [[4, 4]], // 2 [[5, 10]], // 3 [[0, 9]], // 4 [[1, 4], [5, 3]], // 5 [[0, 4], [2, 10], [4, 3]] //] int[] result = DijkstraAlgoForShortestDistance.dijkstra( V, adj, S); System.out.println(Arrays.toString(result)); } }> Pitone # Python implementation of Dijkstra Algorithm import heapq class Node: def __init__(self, v, distance): self.v = v self.distance = distance def __lt__(self, other): return self.distance < other.distance def dijkstra(V, adj, S): visited = [False] * V map = {} q = [] map[S] = Node(S, 0) heapq.heappush(q, Node(S, 0)) while q: n = heapq.heappop(q) v = n.v distance = n.distance visited[v] = True adjList = adj[v] for adjLink in adjList: if not visited[adjLink[0]]: if adjLink[0] not in map: map[adjLink[0]] = Node(v, distance + adjLink[1]) else: sn = map[adjLink[0]] if distance + adjLink[1] < sn.distance: sn.v = v sn.distance = distance + adjLink[1] heapq.heappush(q, Node(adjLink[0], distance + adjLink[1])) result = [0] * V for i in range(V): result[i] = map[i].distance return result def main(): adj = [[] for _ in range(6)] V = 6 E = 5 u = [0, 0, 1, 2, 4] v = [3, 5, 4, 5, 5] w = [9, 4, 4, 10, 3] for i in range(E): edge = [v[i], w[i]] adj[u[i]].append(edge) edge2 = [u[i], w[i]] adj[v[i]].append(edge2) S = 1 result = dijkstra(V, adj, S) print(result) if __name__ == '__main__': main() # This code is contributed by ragul21> C# // C# Code: using System; using System.Collections.Generic; public class Graph { // No. of vertices private int V; // adjacency list private List>[] agg; // Costruttore public Graph(int v) { V = v; agg = nuova lista>[v]; for (int i = 0; i< v; ++i) adj[i] = new List>(); } // funzione per aggiungere un bordo al grafico public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w)); adj[v].Add(Tuple.Create(u, w)); } // stampa il percorso più breve da s public void shortestPath(int s) { // Crea una coda con priorità per memorizzare i vertici che // vengono preelaborati. var pq = nuova PriorityQueue>(); // Crea un vettore per le distanze e inizializza tutte // le distanze come infinite (INF) var dist = new int[V]; for (int i = 0; i< V; i++) dist[i] = int.MaxValue; // Insert source itself in priority queue and // initialize its distance as 0. pq.Enqueue(Tuple.Create(0, s)); dist[s] = 0; /* Looping till priority queue becomes empty (or all distances are not finalized) */ while (pq.Count != 0) { // The first vertex in pair is the minimum // distance vertex, extract it from priority // queue. vertex label is stored in second of // pair (it has to be done this way to keep the // vertices sorted distance (distance must be // first item in pair) var u = pq.Dequeue().Item2; // 'i' is used to get all adjacent vertices of a // vertex foreach(var i in adj[u]) { // Get vertex label and weight of current // adjacent of u. int v = i.Item1; int weight = i.Item2; // If there is shorted path to v through u. if (dist[v]>dist[u] + peso) { // Aggiornamento della distanza di v dist[v] = dist[u] + peso; pq.Enqueue(Tuple.Create(dist[v], v)); } } } // Stampa le distanze più brevi memorizzate in dist[] Console.WriteLine('Vertex Distance from Source'); for (int i = 0; i< V; ++i) Console.WriteLine('{0} {1}', i, dist[i]); } } public class PriorityQueue{Elenco di sola lettura privato_dati; Confronto di sola lettura privata_rispetto; public PriorityQueue(): this(Confronta.Default) { } public PriorityQueue(IComparerconfrontare): this(confrontare.Confrontare) { } public PriorityQueue(Confrontareconfronto) { _data = nuova lista(); _confrontare = confronto; } public void Enqueue(elemento T) { _data.Add(elemento); var childIndex = _data.Count - 1; while (childIndex> 0) { var parentIndex = (childIndex - 1) / 2; if (_compare(_data[childIndex], _data[parentIndex])>= 0) break; T tmp = _data[indicebambino]; _data[childIndex] = _data[parentIndex]; _data[parentIndex] = tmp; indicebambino = indicegenitore; } } public T Dequeue() { // presuppone che pq non sia vuoto; fino al codice chiamante var lastElement = _data.Count - 1; var frontItem = _data[0]; _dati[0] = _dati[ultimoElemento]; _data.RemoveAt(lastElement); --ultimoElemento; var indiceparent = 0; while (true) { var childIndex = parentIndex * 2 + 1; if (childIndex> lastElement) break; // Fine dell'albero var rightChild = childIndex + 1; se (rightChild<= lastElement && _compare(_data[rightChild], _data[childIndex]) < 0) childIndex = rightChild; if (_compare(_data[parentIndex], _data[childIndex]) <= 0) break; // Correct position T tmp = _data[parentIndex]; _data[parentIndex] = _data[childIndex]; _data[childIndex] = tmp; parentIndex = childIndex; } return frontItem; } public T Peek() { T frontItem = _data[0]; return frontItem; } public int Count { get { return _data.Count; } } } class Program { // Driver program to test methods of graph class static void Main(string[] args) { // create the graph given in above figure int V = 7; Graph g = new Graph(V); // making above shown graph g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); } }> Javascript class PriorityQueue { constructor() { this.queue = []; } enqueue(element, priority) { this.queue.push({ element, priority }); this.queue.sort((a, b) =>a.priorità - b.priorità); } dequeue() { if (this.isEmpty()) { return null; } restituisce this.queue.shift().element; } isEmpty() { return this.queue.length === 0; } } class Graph { costruttore(V) { this.V = V; this.adj = nuovo Array(V); per (sia i = 0; i< V; i++) { this.adj[i] = []; } } addEdge(u, v, w) { this.adj[u].push({ v, w }); this.adj[v].push({ v: u, w }); } shortestPath(src) { const pq = new PriorityQueue(); const dist = new Array(this.V).fill(Infinity); const visited = new Array(this.V).fill(false); pq.enqueue(src, 0); dist[src] = 0; while (!pq.isEmpty()) { const u = pq.dequeue(); if (visited[u]) continue; visited[u] = true; for (const { v, w } of this.adj[u]) { if (!visited[v] && dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.enqueue(v, dist[v]); } } } console.log('Vertex Distance from Source'); for (let i = 0; i < this.V; i++) { console.log(`${i} ${dist[i] === Infinity ? 'Infinity' : dist[i]}`); } } } function main() { const V = 7; const g = new Graph(V); g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); } main();> Risposta finale:

Produzione
Analisi della complessità dell'algoritmo di Dijkstra :
- Complessità temporale: O((V + E)logV) , dove V è il numero di vertici ed E è il numero di spigoli.
- Spazio ausiliario: O(V), dove V è il numero di vertici ed E è il numero di archi nel grafico.
2.Implementazione basata su array dell’algoritmo di Dijkstra (approccio naive):
L’algoritmo di Dijkstra può anche essere implementato utilizzando array senza utilizzare una coda prioritaria. Questa implementazione è semplice ma può essere meno efficiente, soprattutto su grafici di grandi dimensioni.
L’algoritmo procede nel modo seguente:
- Inizializza un array per memorizzare le distanze dalla sorgente a ciascun nodo.
- Contrassegna tutti i nodi come non visitati.
- Imposta la distanza dal nodo di origine su 0 e infinito per tutti gli altri nodi.
- Ripeti finché non vengono visitati tutti i nodi:
- Trova il nodo non visitato con la distanza conosciuta più piccola.
- Per il nodo corrente, aggiorna le distanze dei suoi vicini non visitati.
- Contrassegna il nodo corrente come visitato.
Analisi della complessità:
quando è stato inventato il primo computer
- Complessità temporale: O(V^2) nel caso peggiore, dove V è il numero di vertici. Questo può essere migliorato a O(V^2) con alcune ottimizzazioni.
- Spazio ausiliario: O(V), dove V è il numero di vertici ed E è il numero di archi nel grafico.
Algoritmi di Dijkstra vs algoritmo di Bellman-Ford
Algoritmo di Dijkstra e Algoritmo di Bellman-Ford sono entrambi utilizzati per trovare il percorso più breve in un grafico ponderato, ma presentano alcune differenze fondamentali. Ecco le principali differenze tra l’algoritmo di Dijkstra e l’algoritmo di Bellman-Ford:
| Caratteristica: | Quello di Dijkstra | Il fattorino Ford |
|---|---|---|
| Ottimizzazione | ottimizzato per trovare il percorso più breve tra un singolo nodo sorgente e tutti gli altri nodi in un grafico con pesi dei bordi non negativi | L'algoritmo Bellman-Ford è ottimizzato per trovare il percorso più breve tra un singolo nodo sorgente e tutti gli altri nodi in un grafico con pesi degli archi negativi. |
| Rilassamento | L’algoritmo di Dijkstra utilizza un approccio greedy in cui sceglie il nodo con la distanza più piccola e aggiorna i suoi vicini | l'algoritmo Bellman-Ford rilassa tutti i bordi in ogni iterazione, aggiornando la distanza di ciascun nodo considerando tutti i possibili percorsi verso quel nodo |
| Complessità temporale | L’algoritmo di Dijkstra ha una complessità temporale di O(V^2) per un grafo denso e O(E log V) per un grafo sparso, dove V è il numero di vertici ed E è il numero di archi nel grafo. | L'algoritmo di Bellman-Ford ha una complessità temporale pari a O(VE), dove V è il numero di vertici ed E è il numero di archi nel grafico. |
| Pesi negativi | L’algoritmo di Dijkstra non funziona con grafici che hanno pesi degli archi negativi, poiché presuppone che tutti i pesi degli archi siano non negativi. | L'algoritmo di Bellman-Ford è in grado di gestire i pesi dei fronti negativi e di rilevare i cicli di peso negativo nel grafico. |
Algoritmo di Dijkstra contro algoritmo di Floyd-Warshall
Algoritmo di Dijkstra e Algoritmo di Floyd-Warshall sono entrambi utilizzati per trovare il percorso più breve in un grafico ponderato, ma presentano alcune differenze fondamentali. Ecco le principali differenze tra l’algoritmo di Dijkstra e l’algoritmo di Floyd-Warshall:
| Caratteristica: | Quello di Dijkstra | Algoritmo di Floyd-Warshall |
|---|---|---|
| Ottimizzazione | Ottimizzato per trovare il percorso più breve tra un singolo nodo sorgente e tutti gli altri nodi in un grafico con pesi dei bordi non negativi | L'algoritmo di Floyd-Warshall è ottimizzato per trovare il percorso più breve tra tutte le coppie di nodi in un grafico. |
| Tecnica | L’algoritmo di Dijkstra è un algoritmo del percorso più breve a sorgente singola che utilizza un approccio greedy e calcola il percorso più breve dal nodo sorgente a tutti gli altri nodi nel grafico. | L'algoritmo di Floyd-Warshall, d'altra parte, è un algoritmo del percorso più breve per tutte le coppie che utilizza la programmazione dinamica per calcolare il percorso più breve tra tutte le coppie di nodi nel grafico. |
| Complessità temporale | L’algoritmo di Dijkstra ha una complessità temporale di O(V^2) per un grafo denso e O(E log V) per un grafo sparso, dove V è il numero di vertici ed E è il numero di archi nel grafo. | L'algoritmo di Floyd-Warshall, d'altra parte, è un algoritmo del percorso più breve per tutte le coppie che utilizza la programmazione dinamica per calcolare il percorso più breve tra tutte le coppie di nodi nel grafico. |
| Pesi negativi | L’algoritmo di Dijkstra non funziona con grafici che hanno pesi degli archi negativi, poiché presuppone che tutti i pesi degli archi siano non negativi. | L'algoritmo di Floyd-Warshall, d'altra parte, è un algoritmo del percorso più breve per tutte le coppie che utilizza la programmazione dinamica per calcolare il percorso più breve tra tutte le coppie di nodi nel grafico. |
Algoritmo di Dijkstra vs algoritmo A*
Algoritmo di Dijkstra e Algoritmo A* sono entrambi utilizzati per trovare il percorso più breve in un grafico ponderato, ma presentano alcune differenze fondamentali. Ecco le principali differenze tra l’algoritmo di Dijkstra e l’algoritmo A*:
| Caratteristica: | A* Algoritmo | |
|---|---|---|
| Tecnica di ricerca | Ottimizzato per trovare il percorso più breve tra un singolo nodo sorgente e tutti gli altri nodi in un grafico con pesi dei bordi non negativi | L'algoritmo A* è un algoritmo di ricerca informato che utilizza una funzione euristica per guidare la ricerca verso il nodo obiettivo. |
| Funzione euristica | L’algoritmo di Dijkstra non utilizza alcuna funzione euristica e considera tutti i nodi del grafico. | L'algoritmo A* utilizza una funzione euristica che stima la distanza dal nodo corrente al nodo obiettivo. Questa funzione euristica è ammissibile, nel senso che non sovrastima mai la distanza effettiva dal nodo obiettivo |
| Complessità temporale | L’algoritmo di Dijkstra ha una complessità temporale di O(V^2) per un grafo denso e O(E log V) per un grafo sparso, dove V è il numero di vertici ed E è il numero di archi nel grafo. | La complessità temporale dell'algoritmo A* dipende dalla qualità della funzione euristica. |
| Applicazione | L’algoritmo di Dijkstra viene utilizzato in molte applicazioni come algoritmi di routing, sistemi di navigazione GPS e analisi di rete | . L'algoritmo A* è comunemente utilizzato nei problemi di pathfinding e attraversamento di grafici, come videogiochi, robotica e algoritmi di pianificazione. |
Problemi pratici sull'algoritmo di Dijkstra:
- Algoritmo del percorso più breve di Dijkstra | L'avido Algo-7
- Algoritmo di Dijkstra per la rappresentazione della lista di adiacenze | L'avido Algo-8
- Algoritmo di Dijkstra – Coda prioritaria e implementazione dell'array
- Algoritmo del percorso più breve di Dijkstra che utilizza set in STL
- Algoritmo del percorso più breve di Dijkstra che utilizza STL in C++
- Algoritmo del percorso più breve di Dijkstra che utilizza la priorità_queue di STL
- Algoritmo del percorso più breve di Dijkstra che utilizza la matrice in C++
- Algoritmo di Dijkstra per il percorso più breve a sorgente singola in un DAG
- Algoritmo di Dijkstra utilizzando l'heap di Fibonacci
- Algoritmo del cammino minimo di Dijkstra per grafi diretti con pesi negativi
- Stampare percorsi nell’algoritmo del percorso più breve di Dijkstra
- Algoritmo del percorso più breve di Dijkstra con coda prioritaria in Java




