V tomto článku budeme diskutovať o jednom z najznámejších algoritmov najkratšej cesty, t. j. Dijkstrovom algoritme najkratšej cesty, ktorý vyvinul holandský počítačový vedec Edsger W. Dijkstra v roku 1956. Okrem toho urobíme analýzu zložitosti tohto algoritmu a tiež Pozrite sa, ako sa líši od iných algoritmov s najkratšou cestou.
Obsah
- Dijkstrov algoritmus
- Potreba Dijkstrovho algoritmu (účel a prípady použitia)
- Môže Dijkstrov algoritmus fungovať na riadených aj neorientovaných grafoch?
- Algoritmus pre Dijkstrov algoritmus
- Ako funguje Dijkstrov algoritmus?
- Pseudokód pre Dijkstrov algoritmus
- Implementácia Dijkstrovho algoritmu:
- Dijkstrove algoritmy verzus Bellman-Fordov algoritmus
- Dijkstrov algoritmus verzus Floyd-Warshallov algoritmus
- Dijkstrov algoritmus vs A* Algoritmus
- Cvičné problémy s Dijkstrovým algoritmom
- Záver:

Dijkstrov algoritmus:
Dijkstrov algoritmus je populárny algoritmus na riešenie mnohých problémov s najkratšou cestou z jedného zdroja, ktoré majú nezápornú váhu hrán v grafoch, t. j. ide o nájdenie najkratšej vzdialenosti medzi dvoma vrcholmi v grafe. Vymyslel ho holandský počítačový vedec Edsger W. Dijkstra v roku 1956.
Algoritmus udržiava množinu navštívených vrcholov a množinu nenavštívených vrcholov. Začína pri zdrojovom vrchole a opakovane vyberá nenavštívený vrchol s najmenšou predbežnou vzdialenosťou od zdroja. Potom navštívi susedov tohto vrcholu a aktualizuje ich predbežné vzdialenosti, ak sa nájde kratšia cesta. Tento proces pokračuje, kým sa nedosiahne cieľový vrchol alebo kým sa nenavštívia všetky dosiahnuteľné vrcholy.
Potreba Dijkstrovho algoritmu (účel a prípady použitia)
Potreba Dijkstrovho algoritmu vzniká v mnohých aplikáciách, kde je kľúčové nájsť najkratšiu cestu medzi dvoma bodmi.
Napríklad , Môže byť použitý v smerovacích protokoloch pre počítačové siete a tiež používaný v mapových systémoch na nájdenie najkratšej cesty medzi východiskovým bodom a Cieľom (ako je vysvetlené v Ako fungujú Mapy Google? )
Môže Dijkstrov algoritmus fungovať na riadených aj neorientovaných grafoch?
Áno , Dijkstrov algoritmus môže pracovať s orientovanými aj neorientovanými grafmi, pretože tento algoritmus je navrhnutý tak, aby fungoval na akomkoľvek type grafu, pokiaľ spĺňa požiadavky na nezáporné váhy hrán a prepojenie.
- V orientovanom grafe každá hrana má smer, označujúci smer pohybu medzi vrcholmi spojenými hranou. V tomto prípade algoritmus pri hľadaní najkratšej cesty sleduje smer hrán.
- V neorientovanom grafe hrany nemajú žiadny smer a algoritmus sa môže pri hľadaní najkratšej cesty pohybovať pozdĺž hrán dopredu aj dozadu.
Algoritmus pre Dijkstrov algoritmus:
- Označte zdrojový uzol aktuálnou vzdialenosťou 0 a zvyšok nekonečnom.
- Ako aktuálny uzol nastavte nenavštívený uzol s najmenšou aktuálnou vzdialenosťou.
- Pre každého suseda N aktuálneho uzla pripočíta aktuálnu vzdialenosť susedného uzla s váhou spojovacej hrany 0->1. Ak je menšia ako aktuálna vzdialenosť uzla, nastavte ju ako novú aktuálnu vzdialenosť N.
- Označte aktuálny uzol 1 ako navštívený.
- Ak sú nejaké uzly nenavštívené, prejdite na krok 2.
Ako funguje Dijkstrov algoritmus?
Pozrime sa, ako funguje Dijkstrov algoritmus na príklade uvedenom nižšie:
Dijkstrov algoritmus vygeneruje najkratšiu cestu z uzla 0 do všetkých ostatných uzlov v grafe.
Zvážte nasledujúci graf:
Dijkstrov algoritmus
Algoritmus vygeneruje najkratšiu cestu z uzla 0 do všetkých ostatných uzlov v grafe.
Pre tento graf budeme predpokladať, že váha hrán predstavuje vzdialenosť medzi dvoma uzlami.
výmena pamäteAko vidíme, máme najkratšiu cestu z,
Uzol 0 až Uzol 1, od
Uzol 0 až Uzol 2, od
Uzol 0 až Uzol 3, od
Uzol 0 až Uzol 4, od
Uzol 0 až Uzol 6.Na začiatku máme súbor zdrojov uvedených nižšie:
- Vzdialenosť od zdrojového uzla k sebe samému je 0. V tomto príklade je zdrojový uzol 0.
- Vzdialenosť od zdrojového uzla ku všetkým ostatným uzlom nie je známa, takže všetky označíme ako nekonečno.
Príklad: 0 -> 0, 1-> ∞,2-> ∞,3-> ∞,4-> ∞,5-> ∞,6-> ∞.
- budeme mať tiež rad nenavštívených prvkov, ktoré budú sledovať nenavštívené alebo neoznačené uzly.
- Algoritmus sa dokončí, keď sa k ceste pridajú všetky uzly označené ako navštívené a vzdialenosť medzi nimi. Nenavštívené uzly:- 0 1 2 3 4 5 6.
Krok 1: Začnite od uzla 0 a označte uzol ako navštívený, ako môžete skontrolovať na obrázku nižšie Uzol je označený červenou farbou.
Dijkstrov algoritmus
Krok 2: Skontrolujte susediace uzly, Teraz musíme vybrať (Buď si vyberte Uzol 1 so vzdialenosťou 2 alebo Uzol 2 so vzdialenosťou 6 ) a vyberte Uzol s minimálnou vzdialenosťou. V tomto kroku Uzol 1 je Minimálna vzdialenosť priľahlého uzla, preto ho označte ako navštívený a vzdialenosť sčítajte.
Vzdialenosť: Uzol 0 -> Uzol 1 = 2
Dijkstrov algoritmus
Krok 3: Potom sa posuňte dopredu a skontrolujte susedný uzol, ktorý je uzlom 3, označte ho ako navštívený a sčítajte vzdialenosť. Teraz bude vzdialenosť:
if-else príkaz javaVzdialenosť: Uzol 0 -> Uzol 1 -> Uzol 3 = 2 + 5 = 7
Dijkstrov algoritmus
Krok 4: Opäť máme dve možnosti pre susedné Uzly (Buď si môžeme vybrať Uzol 4 so vzdialenosťou 10 alebo buď môžeme zvoliť Uzol 5 so vzdialenosťou 15), takže vyberte Uzol s minimálnou vzdialenosťou. V tomto kroku Uzol 4 je Minimálna vzdialenosť priľahlého uzla, preto ho označte ako navštívený a vzdialenosť sčítajte.
Vzdialenosť: Uzol 0 -> Uzol 1 -> Uzol 3 -> Uzol 4 = 2 + 5 + 10 = 17
Dijkstrov algoritmus
Krok 5: Opäť prejdite dopredu a skontrolujte susedný uzol, ktorý je Uzol 6 , tak to označte ako navštívené a spočítajte vzdialenosť. Teraz bude vzdialenosť:
Vzdialenosť: Uzol 0 -> Uzol 1 -> Uzol 3 -> Uzol 4 -> Uzol 6 = 2 + 5 + 10 + 2 = 19
Dijkstrov algoritmus
Najkratšia vzdialenosť od zdrojového vrcholu je teda 19, čo je optimálne
Pseudokód pre Dijkstrov algoritmus
funkcia Dijkstra(graf, zdroj):
// Inicializuje vzdialenosti ku všetkým uzlom ako nekonečno a k zdrojovému uzlu ako 0.vzdialenosti = mapa (všetky uzly -> nekonečno)
vzdialenosti = 0
// Inicializujte prázdnu množinu navštívených uzlov a prioritný front na sledovanie uzlov, ktoré chcete navštíviť.
navštívená = prázdna množina
front = new PriorityQueue()
queue.enqueue(zdroj, 0)// Slučka, kým nebudú navštívené všetky uzly.
kým fronta nie je prázdna:
// Vyraďte z frontu uzol s najmenšou vzdialenosťou od prioritného frontu.
aktuálny = queue.dequeue()// Ak uzol už bol navštívený, preskočte ho.
ak je aktuálne v navštívených:
ďalej// Označenie uzla ako navštíveného.
navštívené.add(aktuálne)// Skontrolujte všetky susedné uzly, či je potrebné aktualizovať ich vzdialenosti.
pre suseda v Graph.neighbors(aktuálne):
// Vypočítajte predbežnú vzdialenosť od suseda cez aktuálny uzol.
tentative_distance = vzdialenosti[aktuálny] + Graph.distance(aktuálny, susedný)// Ak je predbežná vzdialenosť menšia ako aktuálna vzdialenosť od suseda, aktualizujte vzdialenosť.
ak je predbežná_vzdialenosť
vzdialenosti[neighbor] = predbežná_vzdialenosť// Zaraďte suseda do radu s jeho novou vzdialenosťou, aby sa v budúcnosti zvažovala návšteva.
queue.enqueue(sused, vzdialenosti[sused])// Vráti vypočítané vzdialenosti od zdroja ku všetkým ostatným uzlom v grafe.
spiatočné vzdialenosti
Implementácia Dijkstrovho algoritmu:
Existuje niekoľko spôsobov, ako implementovať Dijkstrov algoritmus, ale najbežnejšie sú:
- Prioritný front (implementácia založená na halde):
- Implementácia založená na poliach:
1. Algoritmus najkratšej cesty Dijkstra pomocou priority_queue (Hromady)
V tejto Implementácii dostaneme graf a zdrojový vrchol v grafe, pričom nájdeme najkratšie cesty od zdroja ku všetkým vrcholom v danom grafe.
najlepší úsmev na svete
Príklad:
Vstup: Zdroj = 0
Príklad
Výkon: Vertex
Vzdialenosť vrcholu od zdroja
0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19
Nižšie je uvedený algoritmus založený na vyššie uvedenej myšlienke:
- Inicializujte hodnoty vzdialenosti a prioritný front.
- Vložte zdrojový uzol do prioritného frontu so vzdialenosťou 0.
- Zatiaľ čo prioritný front nie je prázdny:
- Extrahujte uzol s minimálnou vzdialenosťou od prioritného frontu.
- Aktualizujte vzdialenosti svojich susedov, ak sa nájde kratšia cesta.
- Vložte aktualizovaných susedov do prioritného frontu.
Nižšie je uvedená implementácia vyššie uvedeného prístupu v C++:
C++ // Program to find Dijkstra's shortest path using // priority_queue in STL #include using namespace std; #define INF 0x3f3f3f3f // iPair ==>Integer Pair typedef pair iPair; // Táto trieda predstavuje orientovaný graf pomocou // triedy reprezentácie zoznamu susediacich Graph { int V; // Počet vrcholov // Vo váženom grafe musíme uložiť vrchol // a pár váh pre každý zoznam hrán>* adj; verejné: Graf(int V); // Konštruktor // funkcia na pridanie hrany do grafu void addEdge(int u, int v, int w); // vypíše najkratšiu cestu z s void shortestPath(int s); }; // Alokuje pamäť pre zoznam susediacich Graph::Graph(int V) { this->V = V; adj = nový zoznam [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)); } // Vypíše najkratšie cesty z src do všetkých ostatných vrcholov void Graph::shortestPath(int src) { // Vytvorenie prioritného frontu na ukladanie vrcholov, ktoré // sa predspracujú. Toto je zvláštna syntax v C++. // Podrobnosti o tejto syntaxi nájdete na nižšie uvedenom odkaze // https://www.techcodeview.com priority_queue , väčší > pq; // Vytvorte vektor pre vzdialenosti a inicializujte všetky // vzdialenosti ako nekonečný (INF) vektor dist(V, INF); // Vložte samotný zdroj do prioritného frontu a inicializujte // jeho vzdialenosť ako 0. pq.push(make_pair(0, src)); dist[src] = 0; /* Opakuje sa, kým sa prioritný front nevyprázdni (alebo všetky vzdialenosti nie sú dokončené) */ while (!pq.empty()) { // Prvý vrchol v páre je minimálna vzdialenosť // vrchol, extrahujte ho z prioritného frontu. // označenie vrcholu je uložené v sekunde z páru (musí sa to urobiť // týmto spôsobom, aby sa zachovali vrcholy // zoradená vzdialenosť (vzdialenosť musí byť prvá položka // v páre) int u = pq.top().second; pq.pop(); // 'i' sa používa na získanie všetkých susedných vrcholov // zoznamu vrcholov>::iterátor i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { // Získanie označenia vrcholu a váhy aktuálneho // susediaceho s u. int v = (*i).prvý; int váha = (*i).sekunda; // Ak existuje skrátená cesta k v cez u. if (dist[v]> dist[u] + hmotnosť) { // Aktualizácia vzdialenosti v dist[v] = dist[u] + hmotnosť; pq.push(make_pair(dist[v], v)); } } } // Tlač najkratších vzdialeností uložených v dist[] printf('Vzdialenosť vrcholu od zdroja
'); pre (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; }>
Java import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.PriorityQueue; public class DijkstraAlgoForShortestDistance { static class Node implements Comparable{ int v; int vzdialenosť; public Node(int v, int vzdialenost) { this.v = v; this.vzdialenosť = vzdialenosť; } @Override public int porovnanieTo(Uzol n) { if (this.vzdial<= n.distance) { return -1; } else { return 1; } } } static int[] dijkstra( int V, ArrayList >> adj, int S) { boolean[] navštívené = new boolean[V]; HashMap mapa = new HashMap(); PriorityQueueq = new PriorityQueue(); map.put(S, novy uzol(S, 0)); q.add(new Node(S, 0)); while (!q.isEmpty()) { Node n = q.poll(); int v = n.v; int vzdialenosť = n.vzdialenosť; navštívené[v] = pravda; ArrayList > adjList = adj.get(v); pre (ArrayList adjLink : adjList) { if (visited[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), nový uzol (v, vzdialenosť + adjLink.get(1))); } else { Uzol sn = map.get(adjLink.get(0)); if (vzdialenosť + 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 >> mapa = new HashMap(); int V = 6; int E = 5; int[] u = { 0, 0, 1, 2, 4}; int[] v = { 3, 5, 4, 5, 5}; int[] w = { 9, 4, 4, 10, 3}; pre (int i = 0; i< E; i++) { ArrayList edge = new ArrayList(); hrana.add(v[i]); hrana.add(w[i]); ArrayList > adjList; if (!map.containsKey(u[i])) { adjList = new ArrayList(); } else { adjList = map.get(u[i]); } adjList.add(edge); map.put(u[i], adjList); ArrayList hrana2 = new ArrayList(); hrana2.add(u[i]); hrana2.add(w[i]); ArrayList > adjList2; if (!map.containsKey(v[i])) { adjList2 = new ArrayList(); } else { adjList2 = map.get(v[i]); } adjList2.add(edge2); map.put(v[i], adjList2); } 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)); } }> Python # 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>[] adj; // Verejný konštruktor Graph(int v) { V = v; adj = nový zoznam>[ v]; pre (int i = 0; i< v; ++i) adj[i] = new List>(); } // funkcia na pridanie hrany do grafu public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w)); adj[v].Add(Tuple.Create(u, w)); } // vypíše najkratšiu cestu zo s public void shortestPath(int s) { // Vytvorenie prioritného frontu na uloženie vrcholov, ktoré // sú predspracované. var pq = new PriorityQueue>(); // Vytvorte vektor pre vzdialenosti a inicializujte všetky // vzdialenosti ako nekonečné (INF) var dist = new int[V]; pre (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] + hmotnosť) { // Aktualizácia vzdialenosti v dist[v] = dist[u] + hmotnosť; pq.Enqueue(Tuple.Create(dist[v], v)); } } } // Tlač najkratších vzdialeností uložených v dist[] Console.WriteLine('Vzdialenosť vrcholu od zdroja'); pre (int i = 0; i< V; ++i) Console.WriteLine('{0} {1}', i, dist[i]); } } public class PriorityQueue{ private readonly List_údaje; súkromné porovnanie len na čítanie_porovnaný; public PriorityQueue(): this(Porovnaj.Predvolené) { } public PriorityQueue(IComparerporovnať): this(compare.Compare) { } public PriorityQueue(Comparison)porovnanie) { _data = nový zoznam(); _porovnať = porovnanie; } public void Enqueue(T item) { _data.Add(item); var childIndex = _data.Count - 1; while (childIndex> 0) { var parentIndex = (childIndex - 1) / 2; if (_compare(_data[childIndex], _data[parentIndex])>= 0) break; T tmp = _data[childIndex]; _data[childIndex] = _data[parentIndex]; _data[parentIndex] = tmp; childIndex = parentIndex; } } public T Dequeue() { // predpokladá, že pq nie je prázdne; až po volanie kódu var lastElement = _data.Count - 1; var frontItem = _data[0]; _data[0] = _data[poslednyprvok]; _data.RemoveAt(lastElement); --poslednyprvok; var parentIndex = 0; while (true) { var childIndex = parentIndex * 2 + 1; if (childIndex> lastElement) break; // Koniec stromu var rightChild = childIndex + 1; ak (pravé Dieťa<= 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.priorita - b.priorita); } dequeue() { if (this.isEmpty()) { return null; } return this.queue.shift().prvok; } isEmpty() { return this.queue.length === 0; } } class Graph { konstruktor(V) { this.V = V; this.adj = new Array(V); pre (nech 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();> Konečná odpoveď:

Výkon
Analýza zložitosti Dijkstrovho algoritmu :
- Časová zložitosť: O((V + E) log V) , kde V je počet vrcholov a E je počet hrán.
- Pomocný priestor: O(V), kde V je počet vrcholov a E je počet hrán v grafe.
2.Implementácia Dijkstrovho algoritmu založená na poliach (naivný prístup):
Dijkstrov algoritmus je možné implementovať aj pomocou polí bez použitia prioritného frontu. Táto implementácia je jednoduchá, ale môže byť menej efektívna, najmä na veľkých grafoch.
zoznam polí zoradený
Algoritmus prebieha nasledovne:
- Inicializujte pole na uloženie vzdialeností od zdroja ku každému uzlu.
- Označte všetky uzly ako nenavštívené.
- Nastavte vzdialenosť k zdrojovému uzlu na 0 a nekonečno pre všetky ostatné uzly.
- Opakujte, kým sa nenavštívia všetky uzly:
- Nájdite nenavštívený uzol s najmenšou známou vzdialenosťou.
- Pre aktuálny uzol aktualizujte vzdialenosti jeho nenavštívených susedov.
- Označte aktuálny uzol ako navštívený.
Analýza zložitosti:
- Časová zložitosť: O(V^2) v najhoršom prípade, kde V je počet vrcholov. To sa dá vylepšiť na O(V^2) pomocou niektorých optimalizácií.
- Pomocný priestor: O(V), kde V je počet vrcholov a E je počet hrán v grafe.
Dijkstrove algoritmy verzus Bellman-Fordov algoritmus
Dijkstrov algoritmus a Bellman-Fordov algoritmus obidva sa používajú na nájdenie najkratšej cesty vo váženom grafe, ale majú niekoľko kľúčových rozdielov. Tu sú hlavné rozdiely medzi Dijkstrovým algoritmom a Bellman-Fordovým algoritmom:
| Funkcia: | Dijkstra | Bellman Ford |
|---|---|---|
| Optimalizácia | optimalizované na nájdenie najkratšej cesty medzi jedným zdrojovým uzlom a všetkými ostatnými uzlami v grafe s nezápornými váhami hrán | Algoritmus Bellman-Ford je optimalizovaný na nájdenie najkratšej cesty medzi jedným zdrojovým uzlom a všetkými ostatnými uzlami v grafe so zápornými váhami hrán. |
| Relaxácia | Dijkstrov algoritmus používa nenásytný prístup, kde si vyberie uzol s najmenšou vzdialenosťou a aktualizuje svojich susedov | Algoritmus Bellman-Ford uvoľňuje všetky hrany v každej iterácii a aktualizuje vzdialenosť každého uzla zvážením všetkých možných ciest k tomuto uzlu |
| Časová zložitosť | Dijkstrov algoritmus má časovú zložitosť O(V^2) pre hustý graf a O(E log V) pre riedky graf, kde V je počet vrcholov a E je počet hrán v grafe. | Bellman-Fordov algoritmus má časovú zložitosť O(VE), kde V je počet vrcholov a E je počet hrán v grafe. |
| Záporné váhy | Dijkstrov algoritmus nepracuje s grafmi, ktoré majú záporné váhy hrán, pretože predpokladá, že všetky váhy hrán sú nezáporné. | Algoritmus Bellman-Ford dokáže spracovať záporné váhy hrán a dokáže detekovať cykly záporných váh v grafe. |
Dijkstrov algoritmus verzus Floyd-Warshallov algoritmus
Dijkstrov algoritmus a Floyd-Warshallov algoritmus obidva sa používajú na nájdenie najkratšej cesty vo váženom grafe, ale majú niekoľko kľúčových rozdielov. Tu sú hlavné rozdiely medzi Dijkstrovým algoritmom a Floyd-Warshallovým algoritmom:
| Funkcia: | Dijkstra | Floyd-Warshallov algoritmus |
|---|---|---|
| Optimalizácia | Optimalizované na nájdenie najkratšej cesty medzi jedným zdrojovým uzlom a všetkými ostatnými uzlami v grafe s nezápornými váhami hrán | Floyd-Warshallov algoritmus je optimalizovaný na nájdenie najkratšej cesty medzi všetkými pármi uzlov v grafe. |
| Technika | Dijkstrov algoritmus je jednozdrojový algoritmus najkratšej cesty, ktorý používa chamtivý prístup a vypočítava najkratšiu cestu zo zdrojového uzla do všetkých ostatných uzlov v grafe. | Na druhej strane Floyd-Warshallov algoritmus je algoritmus najkratšej cesty všetkých párov, ktorý používa dynamické programovanie na výpočet najkratšej cesty medzi všetkými pármi uzlov v grafe. |
| Časová zložitosť | Dijkstrov algoritmus má časovú zložitosť O(V^2) pre hustý graf a O(E log V) pre riedky graf, kde V je počet vrcholov a E je počet hrán v grafe. | Na druhej strane Floyd-Warshallov algoritmus je algoritmus najkratšej cesty všetkých párov, ktorý používa dynamické programovanie na výpočet najkratšej cesty medzi všetkými pármi uzlov v grafe. |
| Záporné váhy | Dijkstrov algoritmus nepracuje s grafmi, ktoré majú záporné váhy hrán, pretože predpokladá, že všetky váhy hrán sú nezáporné. | Na druhej strane Floyd-Warshallov algoritmus je algoritmus najkratšej cesty všetkých párov, ktorý používa dynamické programovanie na výpočet najkratšej cesty medzi všetkými pármi uzlov v grafe. |
Dijkstrov algoritmus vs A* Algoritmus
Dijkstrov algoritmus a A* algoritmus obidva sa používajú na nájdenie najkratšej cesty vo váženom grafe, ale majú niekoľko kľúčových rozdielov. Tu sú hlavné rozdiely medzi Dijkstrovým algoritmom a A* algoritmom:
| Funkcia: | A* Algoritmus | |
|---|---|---|
| Technika vyhľadávania | Optimalizované na nájdenie najkratšej cesty medzi jedným zdrojovým uzlom a všetkými ostatnými uzlami v grafe s nezápornými váhami hrán | Algoritmus A* je informovaný vyhľadávací algoritmus, ktorý používa heuristickú funkciu na vedenie vyhľadávania smerom k cieľovému uzlu. |
| Heuristická funkcia | Dijkstrov algoritmus nepoužíva žiadnu heuristickú funkciu a zohľadňuje všetky uzly v grafe. | Algoritmus A* používa heuristickú funkciu, ktorá odhaduje vzdialenosť od aktuálneho uzla k cieľovému uzlu. Táto heuristická funkcia je prípustná, čo znamená, že nikdy nepreceňuje skutočnú vzdialenosť k cieľovému uzlu |
| Časová zložitosť | Dijkstrov algoritmus má časovú zložitosť O(V^2) pre hustý graf a O(E log V) pre riedky graf, kde V je počet vrcholov a E je počet hrán v grafe. | Časová zložitosť A* algoritmu závisí od kvality heuristickej funkcie. |
| Aplikácia | Dijkstrov algoritmus sa používa v mnohých aplikáciách, ako sú algoritmy smerovania, navigačné systémy GPS a analýza siete. | . Algoritmus A* sa bežne používa pri problémoch s hľadaním cesty a prechodom grafov, ako sú videohry, robotika a plánovacie algoritmy. |
Cvičné problémy na Dijkstrovom algoritme:
- Dijkstrov algoritmus najkratšej cesty | Chamtivý Algo-7
- Dijkstrov algoritmus na reprezentáciu zoznamu susedných vzťahov | Chamtivý Algo-8
- Dijkstrov algoritmus – prioritná fronta a implementácia poľa
- Dijkstrov algoritmus najkratšej cesty pomocou sady v STL
- Dijkstrov algoritmus najkratšej cesty pomocou STL v C++
- Dijkstrov algoritmus najkratšej cesty pomocou priority_queue STL
- Dijkstrov algoritmus najkratšej cesty využívajúci maticu v C++
- Dijkstrov algoritmus pre najkratšiu cestu jedného zdroja v DAG
- Dijkstrov algoritmus využívajúci Fibonacciho haldu
- Dijkstrov algoritmus najkratšej cesty pre orientovaný graf so zápornými váhami
- Tlačové cesty v Dijkstrovom algoritme najkratšej cesty
- Algoritmus najkratšej cesty Dijkstra s prioritným frontom v jazyku Java




