Il motivo per utilizzare il tasto di diminuzione anziché il reinserimento dei nodi è di mantenere basso il numero di nodi nella coda di priorità, mantenendo così basso il numero totale di code di priorità rimosse e il costo di ogni bilanciamento della coda di priorità basso.
In un'implementazione dell'algoritmo di Dijkstra che reinserisce i nodi nella coda di priorità con le loro nuove priorità, viene aggiunto un nodo alla coda di priorità per ciascuno degli m archi nel grafico. Ciò significa che ci sono operazioni di accodamento e operazioni di accodamento sulla coda di priorità, dando un tempo di esecuzione totale di O (m T e + m T d ), dove T e è il tempo richiesto per accodarsi nella coda di priorità e T d è il tempo necessario per rimuovere la coda dalla coda prioritaria.
In un'implementazione dell'algoritmo di Dijkstra che supporta la chiave di diminuzione, la coda di priorità che contiene i nodi inizia con n nodi e ad ogni passo dell'algoritmo rimuove un nodo. Ciò significa che il numero totale di heap dequeue è n. Ogni nodo avrà il tasto di diminuzione chiamato potenzialmente una volta per ogni bordo che lo conduce, quindi il numero totale di tasti di diminuzione effettuati è al massimo m. Questo dà un tempo di esecuzione di (n T e + n T d + m T k ), dove T k è il tempo richiesto per chiamare il tasto di diminuzione.
Quindi che effetto ha questo sul runtime? Dipende dalla coda di priorità che usi. Ecco una rapida tabella che mostra diverse code di priorità e i tempi di esecuzione complessivi delle diverse implementazioni dell'algoritmo di Dijkstra:
Queue | T_e | T_d | T_k | w/o Dec-Key | w/Dec-Key
---------------+--------+--------+--------+-------------+---------------
Binary Heap |O(log N)|O(log N)|O(log N)| O(M log N) | O(M log N)
Binomial Heap |O(log N)|O(log N)|O(log N)| O(M log N) | O(M log N)
Fibonacci Heap | O(1) |O(log N)| O(1) | O(M log N) | O(M + N log N)
Come puoi vedere, con la maggior parte dei tipi di code prioritarie, non c'è davvero una differenza nel runtime asintotico e la versione con chiave di diminuzione non è probabile che faccia molto meglio. Tuttavia, se si utilizza un'implementazione dell'heap di Fibonacci della coda di priorità, l'algoritmo di Dijkstra sarà infatti asintoticamente più efficiente quando si utilizza il tasto di diminuzione.
In breve, l'uso del tasto di diminuzione, più una buona coda di priorità, può far cadere il runtime asintotico di Dijkstra oltre ciò che è possibile se continui a fare accodamenti e rimosse dalla coda.
Oltre a questo punto, alcuni algoritmi più avanzati, come l'algoritmo dei percorsi più brevi di Gabow, utilizzano l'algoritmo di Dijkstra come una subroutine e fanno molto affidamento sull'implementazione del tasto di diminuzione. Usano il fatto che se conosci in anticipo l'intervallo di distanze valide, puoi costruire una coda di priorità super efficiente basata su questo fatto.
Spero che questo ti aiuti!