Tässä artikkelissa käsittelemme yhtä yleisimmin tunnetuista lyhimmän polun algoritmeista eli Dijkstran lyhimmän polun algoritmista, jonka hollantilainen tietojenkäsittelytieteilijä Edsger W. Dijkstra kehitti vuonna 1956. Lisäksi teemme tälle algoritmille ja myös monimutkaisuusanalyysin. nähdä, kuinka se eroaa muista lyhimmän polun algoritmeista.
Sisällysluettelo
- Dijkstran algoritmi
- Need for Dijkstra's Algorithm (tarkoitus ja käyttötapaukset)
- Voiko Dijkstran algoritmi toimia sekä suunnatuissa että ohjaamattomissa kaavioissa?
- Algoritmi Dijkstran algoritmille
- Kuinka Dijkstran algoritmi toimii?
- Pseudokoodi Dijkstran algoritmille
- Dijkstran algoritmin toteutus:
- Dijkstran algoritmit vs Bellman-Ford-algoritmi
- Dijkstran algoritmi vs Floyd-Warshall-algoritmi
- Dijkstran algoritmi vs A*-algoritmi
- Harjoittele ongelmia Dijkstran algoritmissa
- Johtopäätös:

Dijkstran algoritmi:
Dijkstran algoritmi on suosittu algoritmi monien yhden lähteen lyhimmän polun ongelmien ratkaisemiseen, joilla on ei-negatiivinen reunapaino graafissa, eli se on löytää graafin kahden kärjen välinen lyhin etäisyys. Sen suunnitteli hollantilainen tietojenkäsittelytieteilijä Edsger W. Dijkstra vuonna 1956.
Algoritmi ylläpitää joukkoa vierailtuja ja vierailtuja pisteitä. Se alkaa lähdepisteestä ja valitsee iteratiivisesti vierailemattoman kärjen, jolla on pienin alustava etäisyys lähteestä. Sitten se vierailee tämän kärjen naapureissa ja päivittää niiden alustavat etäisyydet, jos lyhyempi polku löytyy. Tämä prosessi jatkuu, kunnes kohdepiste on saavutettu tai kaikki saavutettavat kärjet on käyty.
Need for Dijkstra's Algorithm (tarkoitus ja käyttötapaukset)
Dijkstran algoritmin tarve syntyy monissa sovelluksissa, joissa lyhimmän polun löytäminen kahden pisteen välillä on ratkaisevan tärkeää.
Esimerkiksi , Sitä voidaan käyttää tietokoneverkkojen reititysprotokollassa, ja karttajärjestelmät voivat käyttää sitä myös lyhimmän polun löytämiseen aloituspisteen ja määränpään välillä (kuten selitetään kohdassa Miten Google Maps toimii? )
Voiko Dijkstran algoritmi toimia sekä suunnatuissa että ohjaamattomissa kaavioissa?
Joo , Dijkstran algoritmi voi toimia sekä suunnatuissa että suuntaamattomissa kaavioissa, koska tämä algoritmi on suunniteltu toimimaan minkä tahansa tyyppisissä kaavioissa, kunhan se täyttää ei-negatiivisten reunapainojen ja yhteyden vaatimukset.
- Suunnatussa kaaviossa jokaisella reunalla on suunta, joka osoittaa kulkusuunnan reunan yhdistämien kärkien välillä. Tässä tapauksessa algoritmi seuraa reunojen suuntaa etsiessään lyhintä polkua.
- Suuntaamattomassa kaaviossa reunoilla ei ole suuntaa, ja algoritmi voi kulkea sekä eteen- että taaksepäin reunoja pitkin etsiessään lyhintä polkua.
Algoritmi Dijkstran algoritmille:
- Merkitse lähdesolmu virran etäisyydellä 0 ja loput äärettömyydellä.
- Aseta nykyiseksi solmuksi vierailematon solmu, jolla on pienin nykyinen etäisyys.
- Jokaiselle naapurille nykyisen solmun N lisää viereisen solmun nykyisen etäisyyden 0->1 yhdistävän reunan painoon. Jos se on pienempi kuin solmun nykyinen etäisyys, aseta se uudeksi nykyiseksi etäisyydeksi N.
- Merkitse nykyinen solmu 1 käydyksi.
- Siirry vaiheeseen 2, jos solmuja ei ole vierailtu.
Kuinka Dijkstran algoritmi toimii?
Katsotaanpa, kuinka Dijkstran algoritmi toimii alla olevan esimerkin avulla:
Dijkstran algoritmi luo lyhimmän polun solmusta 0 kaikkiin muihin kaavion solmuihin.
Harkitse alla olevaa kaaviota:
Dijkstran algoritmi
Algoritmi luo lyhimmän polun solmusta 0 kaikkiin muihin kaavion solmuihin.
Tässä kaaviossa oletetaan, että reunojen paino edustaa kahden solmun välistä etäisyyttä.
pseudokoodi javaKuten voimme nähdä, meillä on lyhin polku,
Solmu 0 solmuun 1, alkaen
Solmu 0 solmuun 2, alkaen
Solmu 0 solmuun 3 alkaen
Solmu 0 solmuun 4 alkaen
Solmu 0 - solmu 6.Aluksi meillä on alla lueteltu joukko resursseja:
java boolen merkkijono
- Etäisyys lähdesolmusta itseensä on 0. Tässä esimerkissä lähdesolmu on 0.
- Etäisyys lähdesolmusta kaikkiin muihin solmuihin on tuntematon, joten merkitsemme ne kaikki äärettömiksi.
Esimerkki: 0 -> 0, 1-> ∞,2-> ∞,3-> ∞,4-> ∞,5-> ∞,6-> ∞.
- meillä on myös joukko vierailemattomia elementtejä, jotka pitävät kirjaa vierailemattomista tai merkitsemättömistä solmuista.
- Algoritmi valmistuu, kun kaikki solmut on merkitty vierailluiksi ja niiden välinen etäisyys lisätään polkuun. Vierailemattomat solmut:- 0 1 2 3 4 5 6.
Vaihe 1: Aloita solmusta 0 ja merkitse solmu vierailluksi, koska voit kirjautua sisään vieraillun kuvan alla Solmu on merkitty punaisella.
Dijkstran algoritmi
Vaihe 2: Tarkista vierekkäiset solmut. Nyt meidän on tehtävä valintoja (joko valitaan Solmu1 etäisyydellä 2 tai valitaan Solmu 2, jonka etäisyys on 6 ) ja valitaan Solmu vähimmäisetäisyydellä. Tässä vaiheessa Solmu 1 on Minimietäisyys solmun vieressä, joten merkittiin se käydyksi ja lasketaan yhteen etäisyys.
Etäisyys: solmu 0 -> solmu 1 = 2
Dijkstran algoritmi
Vaihe 3: Siirry sitten eteenpäin ja tarkista viereinen solmu, joka on solmu 3, joten merkitsi sen käydyksi ja laske etäisyys. Nyt etäisyys on:
Etäisyys: solmu 0 -> solmu 1 -> solmu 3 = 2 + 5 = 7
Dijkstran algoritmi
Vaihe 4: Meillä on jälleen kaksi vaihtoehtoa vierekkäisille solmuille (joko voimme valita solmun 4, jonka etäisyys on 10, tai joko voimme valita solmun 5, jonka etäisyys on 15), joten valitse solmu, jolla on vähimmäisetäisyys. Tässä vaiheessa Solmu 4 on Minimietäisyys solmun vieressä, joten merkittiin se käydyksi ja lasketaan yhteen etäisyys.
Etäisyys: solmu 0 -> solmu 1 -> solmu 3 -> solmu 4 = 2 + 5 + 10 = 17
Dijkstran algoritmi
Vaihe 5: Siirry jälleen eteenpäin ja tarkista viereinen solmu, joka on Solmu 6 , joten merkitsi sen käydyksi ja laske etäisyys. Nyt etäisyys on:
Etäisyys: solmu 0 -> solmu 1 -> solmu 3 -> solmu 4 -> solmu 6 = 2 + 5 + 10 + 2 = 19
Dijkstran algoritmi
Joten lyhin etäisyys lähdepisteestä on 19, mikä on optimaalinen
Pseudokoodi Dijkstran algoritmille
funktio Dijkstra(kaavio, lähde):
// Alusta etäisyydet kaikkiin solmuihin äärettömäksi ja lähdesolmuun 0:ksi.etäisyydet = kartta (kaikki solmut -> ääretön)
etäisyydet = 0
// Alusta tyhjä joukko vierailtuja solmuja ja prioriteettijono seurataksesi solmuja, joissa vierailla.
vierailtu = tyhjä sarja
jono = uusi PriorityQueue()
queue.enqueue(lähde, 0)// Silmukka kunnes kaikki solmut on käyty.
kun jono ei ole tyhjä:
// Poistaa jonosta solmun, jonka etäisyys prioriteettijonosta on pienin.
nykyinen = queue.dequeue()// Jos solmussa on jo vierailtu, ohita se.
jos nykyinen vieraillut:
jatkaaero ohjelman ja skriptin välillä// Merkitse solmu käydyksi.
visited.add(nykyinen)// Tarkista kaikki naapurisolmut nähdäksesi, tarvitseeko niiden etäisyydet päivittää.
naapurille Graph.neighborsissa (nykyinen):
// Laske alustava etäisyys naapuriin nykyisen solmun kautta.
alustava_etäisyys = etäisyydet[nykyinen] + Graph.distance(nykyinen, naapuri)// Jos alustava etäisyys on pienempi kuin nykyinen etäisyys naapuriin, päivitä etäisyys.
jos alustava_etäisyys
etäisyydet[naapuri] = alustava_etäisyys// Jonota naapuriin sen uudella etäisyydellä, jota harkitaan vierailla tulevaisuudessa.
jono.jono(naapuri, etäisyydet[naapuri])// Palauttaa lasketut etäisyydet lähteestä kaikkiin muihin kaavion solmuihin.
paluumatkat
Dijkstran algoritmin toteutus:
Dijkstra-algoritmin toteuttamiseen on useita tapoja, mutta yleisimmät ovat:
- Prioriteettijono (kekopohjainen toteutus):
- Taulukkopohjainen toteutus:
1. Dijkstran lyhimmän polun algoritmi, joka käyttää prioriteettijonoa (keko)
Tässä toteutuksessa meille annetaan graafi ja graafin lähdepiste, joka löytää lyhimmät reitit lähteestä kaikkiin annetun graafin pisteisiin.
Esimerkki:
Syöte: Lähde = 0
Esimerkki
Lähtö: Vertex
Vertexin etäisyys lähteestä
java ketjuttavat merkkijonot0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19
Alla on algoritmi, joka perustuu yllä olevaan ideaan:
- Alusta etäisyysarvot ja prioriteettijono.
- Lisää lähdesolmu prioriteettijonoon etäisyydellä 0.
- Vaikka prioriteettijono ei ole tyhjä:
- Pura solmu, jonka etäisyys on pienin prioriteettijonosta.
- Päivitä sen naapureiden etäisyydet, jos lyhyempi polku löytyy.
- Lisää päivitetyt naapurit prioriteettijonoon.
Alla on yllä olevan lähestymistavan C++-toteutus:
C++ // Program to find Dijkstra's shortest path using // priority_queue in STL #include using namespace std; #define INF 0x3f3f3f3f // iPair ==>Kokonaislukupari typedef pari iPair; // Tämä luokka edustaa suunnattua graafia käyttäen // vierekkäisyysluettelon esitysluokka Graph { int V; // Piikkien lukumäärä // Painotetussa graafissa meidän on tallennettava kärkipiste // ja painopari jokaiselle reunalistalle>> adj; julkinen: Graph(int V); // Rakentaja // funktio reunan lisäämiseksi graafiin void addEdge(int u, int v, int w); // tulostaa lyhimmän polun kohteesta s void shortestPath(int s); }; // Varaa muistia viereisyysluettelolle Graph::Graph(int V) { this->V = V; adj = uusi lista [V]; } void Graph::lisääEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w)); adj[v].push_back(make_pair(u, w)); } // Tulostaa lyhyimmät polut src:stä kaikkiin muihin pisteisiin void Graph::shortestPath(int src) { // Luo prioriteettijono esikäsiteltyjen pisteiden // tallentamiseen. Tämä on outo syntaksi C++:ssa. // Katso tämän syntaksin yksityiskohdat alla olevasta linkistä // https://www.techcodeview.com priority_queue , suurempi > pq; // Luo vektori etäisyyksille ja alusta kaikki // etäisyydet äärettömäksi (INF) vektoriksi dist(V, INF); // Lisää itse lähde prioriteettijonoon ja alusta // sen etäisyys 0:ksi. pq.push(make_pair(0, src)); dist[src] = 0; /* Silmukka, kunnes prioriteettijonosta tulee tyhjä (tai kaikkia etäisyyksiä ei ole viimeistelty) */ while (!pq.empty()) { // Ensimmäinen parin kärkipiste on minimietäisyys // kärki, erota se prioriteettijonosta. // vertex label tallennetaan parin toiseksi (se // täytyy tehdä tällä tavalla, jotta kärjet säilyvät // lajiteltuna etäisyyden (etäisyyden on oltava ensimmäinen kohde // parissa) int u = pq.top().second; pq.pop(); // 'i' käytetään saamaan // kärkiluettelon kaikki vierekkäiset pisteet>::iteraattori i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { // Hae u:n vieressä olevan virran huippupiste ja paino //. int v = (*i).ensimmäinen; int paino = (*i).sekunti; // Jos polku v:ään on oikosulussa u:n kautta. if (dist[v]> dist[u] + paino) { // V:n päivitysetäisyys dist[v] = dist[u] + paino; pq.push(make_pair(dist[v], v)); } } } // Tulosta lyhyimmät etäisyydet, jotka on tallennettu 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; }>
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 etäisyys; public Node(int v, int etäisyys) { this.v = v; this.distance = etäisyys; } @Ohita julkinen int vertaa(Solmu n) { if (this.distance<= n.distance) { return -1; } else { return 1; } } } static int[] dijkstra( int V, ArrayList >> adj, int S) { boolean[] vieraili = uusi looginen arvo[V]; HashMap kartta = uusi HashMap(); PriorityQueueq = uusi PriorityQueue(); map.put(S, new Node(S, 0)); q.add(uusi solmu(S, 0)); while (!q.isEmpty()) { Solmu n = q.poll(); int v = n.v; int etäisyys = n.etäisyys; vierailtu[v] = tosi; ArrayList > adjList = adj.get(v); for (ArrayList adjLink : adjList) { if (vieraillut[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), uusi solmu (v, etäisyys + adjLink.get(1))); } else { Solmu sn = map.get(adjLink.get(0)); if (etäisyys + 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 >> kartta = uusi 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 }; for (int i = 0; i< E; i++) { ArrayList reuna = new ArrayList(); reuna.add(v[i]); reuna.add(w[i]); ArrayList > adjList; if (!map.containsKey(u[i])) { adjList = new ArrayList(); } else { adjList = kartta.get(u[i]); } adjList.add(edge); map.put(u[i], adjList); ArrayList reuna2 = uusi ArrayList(); reuna2.add(u[i]); reuna2.add(w[i]); ArrayList > adjList2; if (!map.containsKey(v[i])) { adjList2 = new ArrayList(); } else { adjList2 = kartta.get(v[i]); } adjList2.add(edge2); kartta.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)); } }> 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; // Rakentaja public Graph(int v) { V = v; adj = uusi lista>[ v ]; for (int i = 0; i< v; ++i) adj[i] = new List>(); } // funktio reunan lisäämiseksi kuvaajaan public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w)); adj[v].Add(Tuple.Create(u, w)); } // tulostaa lyhimmän polun julkisesta voidista shortestPath(int s) { // Luo prioriteettijono esikäsiteltyjen pisteiden // tallentamiseen. var pq = uusi PriorityQueue>(); // Luo vektori etäisyyksille ja alusta kaikki // etäisyydet äärettömäksi (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] + paino) { // Päivitetään v:n etäisyys dist[v] = dist[u] + paino; pq.Enqueue(Tuple.Create(dist[v], v)); } } } // Tulosta lyhyimmät etäisyydet, jotka on tallennettu dist[] Console.WriteLine('Vertex Distance from Source'); for (int i = 0; i< V; ++i) Console.WriteLine('{0} {1}', i, dist[i]); } } public class PriorityQueue{ yksityinen vain luku -luettelo_data; yksityinen vain luku -vertailu_verrattu; public PriorityQueue(): this(Vertaa.Oletus) { } julkinen PriorityQueue(IComparervertaa): this(vertaa.Vertaa) { } public PriorityQueue(Vertailuvertailu) { _data = uusi luettelo(); _vertaa = vertailu; } public void Enqueue(T item) { _data.Add(nimike); var childIndex = _data.Count - 1; while (childIndex> 0) { var parentIndex = (childIndex - 1) / 2; if (_vertaa(_data[lapsiindeksi], _data[emoindeksi])>= 0) tauko; T tmp = _data[lapsiindeksi]; _data[lapsiindeksi] = _data[emoindeksi]; _data[emoindeksi] = tmp; lapsiindeksi = vanhempiIndex; } } public T Dequeue() { // olettaa, että pq ei ole tyhjä; kutsuvaan koodiin asti var lastElement = _data.Count - 1; var frontItem = _data[0]; _data[0] = _data[viimeinen elementti]; _data.RemoveAt(lastElement); --lastElement; var parentIndex = 0; while (true) { var lapsiIndeksi = vanhempiIndeksi * 2 + 1; if (childIndex> lastElement) tauko; // Puun loppu var rightChild = lapsiIndeksi + 1; jos (oikeaLapsi<= 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.priority - b.priority); } dequeue() { if (this.isEmpty()) { return null; } return this.queue.shift().element; } isEmpty() { return this.queue.length === 0; } } luokkakaavio { rakentaja(V) { this.V = V; this.adj = uusi Array(V); for (olkoon 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();> Lopullinen vastaus:

Lähtö
Dijkstra-algoritmin monimutkaisuusanalyysi :
- Aika monimutkaisuus: O((V + E) log V) , jossa V on kärkien lukumäärä ja E on reunojen lukumäärä.
- Aputila: O(V), jossa V on graafin kärkien lukumäärä ja E on graafin reunojen lukumäärä.
2.Dijkstran algoritmin taulukkopohjainen toteutus (naiivi lähestymistapa):
Dijkstran algoritmi voidaan toteuttaa myös taulukoiden avulla ilman prioriteettijonoa. Tämä toteutus on yksinkertaista, mutta se voi olla vähemmän tehokas, etenkin suurilla kaavioilla.
Algoritmi etenee seuraavasti:
- Alusta taulukko tallentaaksesi etäisyydet lähteestä kuhunkin solmuun.
- Merkitse kaikki solmut vierailemattomiksi.
- Aseta etäisyydeksi lähdesolmuun 0 ja äärettömäksi kaikille muille solmuille.
- Toista, kunnes kaikki solmut on käyty:
- Etsi vierailematon solmu, jolla on pienin tunnettu etäisyys.
- Päivitä nykyisen solmun vierailemattomien naapureiden etäisyydet.
- Merkitse nykyinen solmu vierailluksi.
Monimutkaisuusanalyysi:
- Aika monimutkaisuus: O(V^2) pahimmassa tapauksessa, jossa V on pisteiden lukumäärä. Tämä voidaan parantaa arvoon O(V^2) joillain optimoinnilla.
- Aputila: O(V), jossa V on graafin kärkien lukumäärä ja E on graafin reunojen lukumäärä.
Dijkstran algoritmit vs Bellman-Ford-algoritmi
Dijkstran algoritmi ja Bellman-Ford-algoritmi molempia käytetään lyhimmän polun löytämiseen painotetussa kaaviossa, mutta niillä on joitain keskeisiä eroja. Tässä ovat tärkeimmät erot Dijkstran algoritmin ja Bellman-Ford-algoritmin välillä:
| Ominaisuus: | Dijkstran | Bellman Ford |
|---|---|---|
| Optimointi | optimoitu etsimään lyhimmän polun yksittäisen lähdesolmun ja kaikkien muiden graafin solmujen välillä ei-negatiivisilla reunapainoilla | Bellman-Ford-algoritmi on optimoitu löytämään lyhimmän polun yhden lähdesolmun ja kaikkien muiden graafin solmujen välillä negatiivisilla reunapainoilla. |
| Rentoutuminen | Dijkstran algoritmi käyttää ahneutta, jossa se valitsee solmun, jolla on pienin etäisyys, ja päivittää sen naapurit | Bellman-Ford-algoritmi rentouttaa jokaisen iteroinnin kaikki reunat päivittäen kunkin solmun etäisyyden ottamalla huomioon kaikki mahdolliset polut kyseiseen solmuun |
| Aika monimutkaisuus | Dijkstran algoritmin aikamonimutkaisuus on O(V^2) tiheälle graafille ja O(E log V) harvalle graafille, missä V on pisteiden lukumäärä ja E on graafin reunojen lukumäärä. | Bellman-Ford-algoritmin aikakompleksisuus on O(VE), jossa V on graafin kärkien lukumäärä ja E on graafin reunojen lukumäärä. |
| Negatiiviset painot | Dijkstran algoritmi ei toimi graafien kanssa, joilla on negatiivinen reunapainotus, koska se olettaa, että kaikki reunapainot eivät ole negatiivisia. | Bellman-Ford-algoritmi pystyy käsittelemään negatiivisia reunapainotuksia ja havaitsemaan negatiivisen painotuksen jaksot kaaviossa. |
Dijkstran algoritmi vs Floyd-Warshall-algoritmi
Dijkstran algoritmi ja Floyd-Warshall-algoritmi molempia käytetään lyhimmän polun löytämiseen painotetussa kaaviossa, mutta niillä on joitain keskeisiä eroja. Tässä ovat tärkeimmät erot Dijkstran algoritmin ja Floyd-Warshall-algoritmin välillä:
| Ominaisuus: | Dijkstran | Floyd-Warshall-algoritmi |
|---|---|---|
| Optimointi | Optimoitu lyhimmän polun löytämiseen yhden lähdesolmun ja kaikkien muiden graafin solmujen välillä ei-negatiivisilla reunapainoilla | Floyd-Warshall-algoritmi on optimoitu lyhimmän polun löytämiseen kaavion kaikkien solmuparien välillä. |
| Tekniikka | Dijkstran algoritmi on yhden lähteen lyhimmän polun algoritmi, joka käyttää ahneutta ja laskee lyhimmän reitin lähdesolmusta kaikkiin muihin kaavion solmuihin. | Floyd-Warshall-algoritmi puolestaan on kaikkien parien lyhimmän polun algoritmi, joka laskee dynaamisen ohjelmoinnin avulla lyhimmän polun kaikkien kaavion solmuparien välillä. |
| Aika monimutkaisuus | Dijkstran algoritmin aikamonimutkaisuus on O(V^2) tiheälle graafille ja O(E log V) harvalle graafille, missä V on pisteiden lukumäärä ja E on graafin reunojen lukumäärä. | Floyd-Warshall-algoritmi puolestaan on kaikkien parien lyhimmän polun algoritmi, joka laskee dynaamisen ohjelmoinnin avulla lyhimmän polun kaikkien kaavion solmuparien välillä. |
| Negatiiviset painot | Dijkstran algoritmi ei toimi graafien kanssa, joilla on negatiivinen reunapainotus, koska se olettaa, että kaikki reunapainot eivät ole negatiivisia. | Floyd-Warshall-algoritmi puolestaan on kaikkien parien lyhimmän polun algoritmi, joka laskee dynaamisen ohjelmoinnin avulla lyhimmän polun kaikkien kaavion solmuparien välillä. |
Dijkstran algoritmi vs A*-algoritmi
Dijkstran algoritmi ja A* algoritmi molempia käytetään lyhimmän polun löytämiseen painotetussa kaaviossa, mutta niillä on joitain keskeisiä eroja. Tässä ovat tärkeimmät erot Dijkstran algoritmin ja A*-algoritmin välillä:
| Ominaisuus: | A* Algoritmi | |
|---|---|---|
| Hakutekniikka | Optimoitu lyhimmän polun löytämiseen yhden lähdesolmun ja kaikkien muiden graafin solmujen välillä ei-negatiivisilla reunapainoilla | A*-algoritmi on tietoinen hakualgoritmi, joka ohjaa haun kohti tavoitesolmua heuristisen funktion avulla. |
| Heuristinen funktio | Dijkstran algoritmi, ei käytä mitään heuristista funktiota ja ottaa huomioon kaikki kaavion solmut. | A*-algoritmi käyttää heuristista funktiota, joka arvioi etäisyyden nykyisestä solmusta tavoitesolmuun. Tämä heuristinen funktio on sallittu, mikä tarkoittaa, että se ei koskaan yliarvioi todellista etäisyyttä tavoitesolmuun |
| Aika monimutkaisuus | Dijkstran algoritmin aikamonimutkaisuus on O(V^2) tiheälle graafille ja O(E log V) harvalle graafille, missä V on pisteiden lukumäärä ja E on graafin reunojen lukumäärä. | A*-algoritmin aikamonimutkaisuus riippuu heuristisen funktion laadusta. |
| Sovellus | Dijkstran algoritmia käytetään monissa sovelluksissa, kuten reititysalgoritmeissa, GPS-navigointijärjestelmissä ja verkkoanalyysissä | . A*-algoritmia käytetään yleisesti polunhaku- ja kuvaajan läpikulkuongelmissa, kuten videopeleissä, robotiikassa ja suunnittelualgoritmeissa. |
Harjoittele ongelmia Dijkstran algoritmissa:
- Dijkstran lyhimmän polun algoritmi | Ahne Algo-7
- Dijkstran algoritmi vierekkäisyysluettelon esittämiseen | Ahne Algo-8
- Dijkstran algoritmi – prioriteettijono ja taulukon toteutus
- Dijkstran lyhimmän polun algoritmi käyttäen settiä STL:ssä
- Dijkstran lyhin polun algoritmi, joka käyttää STL:ää C++:ssa
- Dijkstran lyhimmän polun algoritmi, joka käyttää STL:n prioriteettijonoa
- Dijkstran lyhimmän polun algoritmi, joka käyttää matriisia C++:ssa
- Dijkstran algoritmi yhden lähteen lyhimmälle polulle DAG:ssa
- Dijkstran algoritmi Fibonacci Heapilla
- Dijkstran lyhimmän polun algoritmi suunnatulle graafille negatiivisilla painoilla
- Tulosta polkuja Dijkstran lyhimmän polun algoritmilla
- Dijkstran lyhimmän polun algoritmi prioriteettijonolla Javassa




