Čo je Dijkstrov algoritmus? | Úvod do Dijkstrovho algoritmu najkratšej cesty
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.
Ako 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ť:
Vzdialenosť: 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.
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(); PriorityQueue q = 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(IComparer porovnať): 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.
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