In diesem Artikel werden wir einen der bekanntesten Algorithmen für kürzeste Wege diskutieren, nämlich Dijkstras Kürzeste-Weg-Algorithmus, der 1956 vom niederländischen Informatiker Edsger W. Dijkstra entwickelt wurde. Darüber hinaus werden wir eine Komplexitätsanalyse für diesen Algorithmus durchführen Sehen Sie, wie es sich von anderen Kürzeste-Weg-Algorithmen unterscheidet.
Inhaltsverzeichnis
- Dijkstras Algorithmus
- Notwendigkeit des Dijkstra-Algorithmus (Zweck und Anwendungsfälle)
- Funktioniert der Dijkstra-Algorithmus sowohl für gerichtete als auch für ungerichtete Graphen?
- Algorithmus für Dijkstras Algorithmus
- Wie funktioniert der Dijkstra-Algorithmus?
- Pseudocode für Dijkstras Algorithmus
- Implementierung des Dijkstra-Algorithmus:
- Dijkstras Algorithmen vs. Bellman-Ford-Algorithmus
- Dijkstras Algorithmus vs. Floyd-Warshall-Algorithmus
- Dijkstras Algorithmus vs. A*-Algorithmus
- Übungsaufgaben zum Dijkstra-Algorithmus
- Abschluss:

Dijkstras Algorithmus:
Dijkstras Algorithmus ist ein beliebter Algorithmus zur Lösung vieler Single-Source-Kürzeste-Wege-Probleme mit nicht negativem Kantengewicht in den Diagrammen, d. h. es geht darum, den kürzesten Abstand zwischen zwei Scheitelpunkten in einem Diagramm zu finden. Es wurde von einem niederländischen Informatiker konzipiert Edsger W. Dijkstra im Jahr 1956.
Der Algorithmus verwaltet eine Reihe besuchter Scheitelpunkte und eine Reihe nicht besuchter Scheitelpunkte. Es beginnt am Quellscheitelpunkt und wählt iterativ den nicht besuchten Scheitelpunkt mit dem kleinsten vorläufigen Abstand von der Quelle aus. Anschließend besucht es die Nachbarn dieses Scheitelpunkts und aktualisiert deren vorläufige Entfernungen, wenn ein kürzerer Pfad gefunden wird. Dieser Vorgang wird fortgesetzt, bis der Zielscheitelpunkt erreicht ist oder alle erreichbaren Scheitelpunkte besucht wurden.
Notwendigkeit des Dijkstra-Algorithmus (Zweck und Anwendungsfälle)
Der Bedarf für den Dijkstra-Algorithmus entsteht in vielen Anwendungen, bei denen es entscheidend ist, den kürzesten Weg zwischen zwei Punkten zu finden.
Zum Beispiel , Es kann in den Routing-Protokollen für Computernetzwerke und auch von Kartensystemen verwendet werden, um den kürzesten Weg zwischen Startpunkt und Ziel zu finden (wie in erläutert). Wie funktioniert Google Maps? )
Funktioniert der Dijkstra-Algorithmus sowohl für gerichtete als auch für ungerichtete Graphen?
Ja , Dijkstras Algorithmus kann sowohl auf gerichteten als auch auf ungerichteten Graphen arbeiten, da dieser Algorithmus für die Arbeit mit jeder Art von Graph ausgelegt ist, solange er die Anforderungen erfüllt, nicht negative Kantengewichte zu haben und verbunden zu sein.
- In einem gerichteten Graphen Jede Kante hat eine Richtung, die die Bewegungsrichtung zwischen den durch die Kante verbundenen Eckpunkten angibt. In diesem Fall folgt der Algorithmus bei der Suche nach dem kürzesten Weg der Richtung der Kanten.
- In einem ungerichteten Graphen Die Kanten haben keine Richtung und der Algorithmus kann bei der Suche nach dem kürzesten Weg entlang der Kanten sowohl vorwärts als auch rückwärts traversieren.
Algorithmus für Dijkstras Algorithmus:
- Markieren Sie den Quellknoten mit einem aktuellen Abstand von 0 und den Rest mit unendlich.
- Legen Sie den nicht besuchten Knoten mit der kleinsten aktuellen Entfernung als aktuellen Knoten fest.
- Für jeden Nachbarn addiert N des aktuellen Knotens den aktuellen Abstand des benachbarten Knotens mit dem Gewicht der Kante, die 0->1 verbindet. Wenn er kleiner als der aktuelle Abstand von Node ist, legen Sie ihn als neuen aktuellen Abstand von N fest.
- Markieren Sie den aktuellen Knoten 1 als besucht.
- Fahren Sie mit Schritt 2 fort, wenn Knoten vorhanden sind, die nicht besucht werden.
Wie funktioniert der Dijkstra-Algorithmus?
Sehen wir uns anhand des folgenden Beispiels an, wie der Dijkstra-Algorithmus funktioniert:
Der Dijkstra-Algorithmus generiert den kürzesten Pfad von Knoten 0 zu allen anderen Knoten im Diagramm.
Betrachten Sie die folgende Grafik:
Dijkstras Algorithmus
Der Algorithmus generiert den kürzesten Pfad von Knoten 0 zu allen anderen Knoten im Diagramm.
Für dieses Diagramm gehen wir davon aus, dass das Gewicht der Kanten den Abstand zwischen zwei Knoten darstellt.
CSS-DeckkraftübergangWie wir sehen können, haben wir den kürzesten Weg von:
Knoten 0 bis Knoten 1, von
Knoten 0 bis Knoten 2, von
Knoten 0 bis Knoten 3, von
Knoten 0 bis Knoten 4, von
Knoten 0 bis Knoten 6.Zunächst verfügen wir über eine Reihe von Ressourcen, die unten aufgeführt sind:
- Der Abstand vom Quellknoten zu sich selbst beträgt 0. In diesem Beispiel ist der Quellknoten 0.
- Der Abstand vom Quellknoten zu allen anderen Knoten ist unbekannt, daher markieren wir alle als unendlich.
Beispiel: 0 -> 0, 1 -> ∞,2 -> ∞,3 -> ∞,4 -> ∞,5 -> ∞,6 -> ∞.
Bullen gegen Ochsen
- Wir werden auch über ein Array nicht besuchter Elemente verfügen, das nicht besuchte oder nicht markierte Knoten verfolgt.
- Der Algorithmus wird abgeschlossen, wenn alle Knoten als besucht markiert sind und der Abstand zwischen ihnen zum Pfad hinzugefügt wird. Nicht besuchte Knoten: - 0 1 2 3 4 5 6.
Schritt 1: Beginnen Sie mit Knoten 0 und markieren Sie den Knoten als besucht, wie Sie im Bild unten sehen können. Der besuchte Knoten ist rot markiert.
Dijkstras Algorithmus
Schritt 2: Suchen Sie nach benachbarten Knoten. Jetzt müssen wir eine Auswahl treffen (entweder Knoten1 mit Abstand 2 oder Knoten 2 mit Abstand 6) und Knoten mit minimalem Abstand auswählen. In diesem Schritt Knoten 1 ist der Mindestabstand zum benachbarten Knoten. Markieren Sie ihn daher als besucht und addieren Sie den Abstand.
Entfernung: Knoten 0 -> Knoten 1 = 2
Dijkstras Algorithmus
Schritt 3: Gehen Sie dann vorwärts und suchen Sie nach dem benachbarten Knoten, der Knoten 3 ist. Markieren Sie ihn also als besucht und addieren Sie die Entfernung. Die Entfernung beträgt nun:
Entfernung: Knoten 0 -> Knoten 1 -> Knoten 3 = 2 + 5 = 7
Dijkstras Algorithmus
Schritt 4: Auch hier haben wir zwei Möglichkeiten für benachbarte Knoten (entweder können wir Knoten 4 mit Abstand 10 oder Knoten 5 mit Abstand 15 wählen), also wählen wir Knoten mit minimalem Abstand. In diesem Schritt Knoten 4 ist der Mindestabstand zum benachbarten Knoten. Markieren Sie ihn daher als besucht und addieren Sie den Abstand.
Entfernung: Knoten 0 -> Knoten 1 -> Knoten 3 -> Knoten 4 = 2 + 5 + 10 = 17
Dijkstras Algorithmus
Schritt 5: Bewegen Sie sich erneut vorwärts und prüfen Sie, ob ein benachbarter Knoten vorhanden ist Knoten 6 Markieren Sie es also als besucht und addieren Sie die Entfernung. Die Entfernung beträgt nun:
Entfernung: Knoten 0 -> Knoten 1 -> Knoten 3 -> Knoten 4 -> Knoten 6 = 2 + 5 + 10 + 2 = 19
Dijkstras Algorithmus
Der kürzeste Abstand vom Quellscheitelpunkt beträgt also 19, was optimal ist
Pseudocode für Dijkstras Algorithmus
Funktion Dijkstra(Grafik, Quelle):
// Distanzen zu allen Knoten als unendlich und zum Quellknoten als 0 initialisieren.Entfernungen = Karte (alle Knoten -> Unendlich)
Abstände = 0
// Initialisieren Sie einen leeren Satz besuchter Knoten und eine Prioritätswarteschlange, um den Überblick über die zu besuchenden Knoten zu behalten.
besucht = leere Menge
queue = new PriorityQueue()
queue.enqueue(Quelle, 0)// Schleife, bis alle Knoten besucht wurden.
solange die Warteschlange nicht leer ist:
// Den Knoten mit der geringsten Entfernung von der Prioritätswarteschlange aus der Warteschlange entfernen.
current = queue.dequeue()// Wenn der Knoten bereits besucht wurde, überspringen Sie ihn.
falls aktuell in besucht:
weitermachen// Markiere den Knoten als besucht.
besuchte.add(aktuell)jsp javatpoint// Überprüfen Sie alle benachbarten Knoten, um zu sehen, ob ihre Abstände aktualisiert werden müssen.
für Nachbarn in Graph.neighbors(current):
// Berechnen Sie die vorläufige Entfernung zum Nachbarn durch den aktuellen Knoten.
tentative_distance = Abstände[aktuell] + Graph.distance(aktuell, Nachbar)// Wenn der vorläufige Abstand kleiner ist als der aktuelle Abstand zum Nachbarn, aktualisiere den Abstand.
wenn tentative_distance
distances[neighbor] = tentative_distance// Den Nachbarn mit seiner neuen Entfernung in die Warteschlange stellen, damit er für zukünftige Besuche berücksichtigt wird.
queue.enqueue(neighbor, distances[neighbor])// Die berechneten Abstände von der Quelle zu allen anderen Knoten im Diagramm zurückgeben.
Rückwege
Implementierung des Dijkstra-Algorithmus:
Es gibt mehrere Möglichkeiten, den Dijkstra-Algorithmus zu implementieren, die gebräuchlichsten sind jedoch:
- Prioritätswarteschlange (Heap-basierte Implementierung):
- Array-basierte Implementierung:
1. Dijkstras Shortest-Path-Algorithmus unter Verwendung von Priority_queue (Heap)
In dieser Implementierung erhalten wir einen Graphen und einen Quellscheitelpunkt im Graphen und finden die kürzesten Pfade von der Quelle zu allen Scheitelpunkten im gegebenen Graphen.
Beispiel:
Eingang: Quelle = 0
Beispiel
Ausgabe: Scheitel
Scheitelpunktabstand von der Quelle
0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19Vernetzung und Typen
Unten ist der Algorithmus, der auf der obigen Idee basiert:
- Initialisieren Sie die Distanzwerte und die Prioritätswarteschlange.
- Fügen Sie den Quellknoten mit der Distanz 0 in die Prioritätswarteschlange ein.
- Während die Prioritätswarteschlange nicht leer ist:
- Extrahieren Sie den Knoten mit dem minimalen Abstand von der Prioritätswarteschlange.
- Aktualisieren Sie die Entfernungen seiner Nachbarn, wenn ein kürzerer Pfad gefunden wird.
- Fügen Sie aktualisierte Nachbarn in die Prioritätswarteschlange ein.
Nachfolgend finden Sie die C++-Implementierung des oben genannten Ansatzes:
C++ // Program to find Dijkstra's shortest path using // priority_queue in STL #include using namespace std; #define INF 0x3f3f3f3f // iPair ==>Integer-Paar Typedef-Paar iPair; // Diese Klasse repräsentiert einen gerichteten Graphen mit // Adjazenzlistendarstellung class Graph { int V; // Anzahl der Scheitelpunkte // In einem gewichteten Diagramm müssen wir Scheitelpunkte // und Gewichtspaare für jede Kantenliste speichern>* adj; public: Graph(int V); // Konstruktor // Funktion zum Hinzufügen einer Kante zum Diagramm void addEdge(int u, int v, int w); // druckt den kürzesten Pfad von s void shortestPath(int s); }; // Reserviert Speicher für Adjazenzliste Graph::Graph(int V) { this->V = V; adj = neue Liste [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)); } // Druckt die kürzesten Pfade von src zu allen anderen Scheitelpunkten. void Graph::shortestPath(int src) { // Erstellen Sie eine Prioritätswarteschlange, um Scheitelpunkte zu speichern, die // vorverarbeitet werden. Das ist eine seltsame Syntax in C++. // Einzelheiten zu dieser Syntax finden Sie unter dem folgenden Link // https://www.techcodeview.com Priority_queue , größer > pq; // Erstelle einen Vektor für Entfernungen und initialisiere alle // Entfernungen als unendlichen (INF) Vektor dist(V, INF); // Quelle selbst in Prioritätswarteschlange einfügen und // ihren Abstand als 0 initialisieren. pq.push(make_pair(0, src)); dist[src] = 0; /* Schleife, bis die Prioritätswarteschlange leer wird (oder nicht alle Abstände festgelegt sind) */ while (!pq.empty()) { // Der erste Scheitelpunkt im Paar ist der Mindestabstand // Scheitelpunkt, extrahiere ihn aus der Prioritätswarteschlange. // Die Scheitelpunktbeschriftung wird im zweiten Teil des Paares gespeichert (dies // muss auf diese Weise erfolgen, um den // sortierten Abstand der Scheitelpunkte beizubehalten (der Abstand muss das erste Element // im Paar sein) int u = pq.top().second; pq.pop(); // 'i' wird verwendet, um alle benachbarten Scheitelpunkte einer // Scheitelpunktliste abzurufen>::iterator i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { // Scheitelpunktbezeichnung und Gewicht des aktuellen // Nachbars von u abrufen. int v = (*i).first; int Weight = (*i).second; // Wenn es einen kurzen Pfad zu v durch u gibt. if (dist[v]> dist[u] + Gewicht) { // Abstand von v aktualisieren dist[v] = dist[u] + Gewicht; pq.push(make_pair(dist[v], v)); } } } // Kürzeste in dist[] gespeicherte Abstände drucken printf('Vertex Distance from Source
'); für (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{ im Fernsehen; int Abstand; public Node(int v, int distance) { this.v = v; this.distance = Abstand; } @Override public int CompareTo(Node n) { if (this.distance<= n.distance) { return -1; } else { return 1; } } } static int[] dijkstra( int V, ArrayList >> adj, int S) { boolean[] besuchte = new boolean[V]; HashMap map = new HashMap(); Prioritätswarteschlangeq = new PriorityQueue(); map.put(S, neuer Knoten(S, 0)); q.add(new Node(S, 0)); while (!q.isEmpty()) { Node n = q.poll(); int v = n.v; int distance = n.distance; besuchte[v] = wahr; Anordnungsliste > adjList = adj.get(v); für (ArrayList adjLink : adjList) { if (visited[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), new Node (v, Abstand + adjLink.get(1))); } else { Node sn = map.get(adjLink.get(0)); if (Entfernung + 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 >> map = 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 }; für (int i = 0; i< E; i++) { ArrayList Kante = neue ArrayList(); edge.add(v[i]); edge.add(w[i]); Anordnungsliste > adjList; if (!map.containsKey(u[i])) { adjList = new ArrayList(); } else { adjList = map.get(u[i]); } adjList.add(edge); map.put(u[i], adjList); Anordnungsliste edge2 = new ArrayList(); edge2.add(u[i]); edge2.add(w[i]); Anordnungsliste > adjList2; if (!map.containsKey(v[i])) { adjList2 = new ArrayList(); } else { adjList2 = map.get(v[i]); } adjList2.add(edge2); map.put(v[i], adjList2); } für (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; // Konstruktor public Graph(int v) { V = v; adj = neue Liste>[ v ]; für (int i = 0; i< v; ++i) adj[i] = new List>(); } // Funktion zum Hinzufügen einer Kante zum Diagramm public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w)); adj[v].Add(Tuple.Create(u, w)); } // druckt den kürzesten Pfad aus s public void shortestPath(int s) { // Erstellen Sie eine Prioritätswarteschlange, um Scheitelpunkte zu speichern, die // vorverarbeitet werden. var pq = neue PriorityQueue>(); // Erstelle einen Vektor für Abstände und initialisiere alle // Abstände als unendlich (INF) var dist = new int[V]; für (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] + Gewicht) { // Abstand von v aktualisieren dist[v] = dist[u] + Gewicht; pq.Enqueue(Tuple.Create(dist[v], v)); } } } // Kürzeste in dist[] gespeicherte Abstände drucken Console.WriteLine('Vertex Distance from Source'); für (int i = 0; i< V; ++i) Console.WriteLine('{0} {1}', i, dist[i]); } } public class PriorityQueue{ private schreibgeschützte Liste_Daten; privater schreibgeschützter Vergleich_verglichen; public PriorityQueue(): this(Vergleiche.Default) { } public PriorityQueue(IComparervergleichen): this(compare.Compare) { } public PriorityQueue(ComparisonVergleich) { _data = neue Liste(); _compare = Vergleich; } 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() { // geht davon aus, dass pq nicht leer ist; bis zum Aufrufcode var lastElement = _data.Count - 1; var frontItem = _data[0]; _data[0] = _data[lastElement]; _data.RemoveAt(lastElement); --lastElement; var parentIndex = 0; while (true) { var childIndex = parentIndex * 2 + 1; if (childIndex> lastElement) break; // Ende des Baums var rightChild = childIndex + 1; if (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ät - b.Priorität); } dequeue() { if (this.isEmpty()) { return null; } return this.queue.shift().element; } isEmpty() { return this.queue.length === 0; } } class Graph { constructionor(V) { this.V = V; this.adj = neues Array(V); für (sei 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();> Endgültige Antwort:

Ausgabe
Komplexitätsanalyse des Dijkstra-Algorithmus :
- Zeitkomplexität: O((V + E) log V) , Dabei ist V die Anzahl der Eckpunkte und E die Anzahl der Kanten.
- Hilfsraum: O(V), wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten im Diagramm ist.
2.Array-basierte Implementierung des Dijkstra-Algorithmus (naiver Ansatz):
Der Dijkstra-Algorithmus kann auch mithilfe von Arrays ohne Verwendung einer Prioritätswarteschlange implementiert werden. Diese Implementierung ist unkompliziert, kann jedoch insbesondere bei großen Diagrammen weniger effizient sein.
Der Algorithmus läuft wie folgt ab:
- Initialisieren Sie ein Array, um Entfernungen von der Quelle zu jedem Knoten zu speichern.
- Markieren Sie alle Knoten als nicht besucht.
- Legen Sie den Abstand zum Quellknoten auf 0 und für alle anderen Knoten auf Unendlich fest.
- Wiederholen, bis alle Knoten besucht sind:
- Finden Sie den nicht besuchten Knoten mit der kleinsten bekannten Entfernung.
- Aktualisieren Sie für den aktuellen Knoten die Entfernungen seiner nicht besuchten Nachbarn.
- Markieren Sie den aktuellen Knoten als besucht.
Komplexitätsanalyse:
- Zeitkomplexität: O(V^2) im schlimmsten Fall, wobei V die Anzahl der Eckpunkte ist. Dies kann mit einigen Optimierungen auf O(V^2) verbessert werden.
- Hilfsraum: O(V), wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten im Diagramm ist.
Dijkstras Algorithmen vs. Bellman-Ford-Algorithmus
Dijkstras Algorithmus und Bellman-Ford-Algorithmus werden beide verwendet, um den kürzesten Weg in einem gewichteten Diagramm zu finden, weisen jedoch einige wesentliche Unterschiede auf. Hier sind die Hauptunterschiede zwischen dem Dijkstra-Algorithmus und dem Bellman-Ford-Algorithmus:
| Besonderheit: | Dijkstras | Bellman Ford |
|---|---|---|
| Optimierung | Optimiert für die Suche nach dem kürzesten Pfad zwischen einem einzelnen Quellknoten und allen anderen Knoten in einem Diagramm mit nicht negativen Kantengewichten | Der Bellman-Ford-Algorithmus ist für die Suche nach dem kürzesten Pfad zwischen einem einzelnen Quellknoten und allen anderen Knoten in einem Diagramm mit negativen Kantengewichten optimiert. |
| Entspannung | Der Dijkstra-Algorithmus verwendet einen gierigen Ansatz, bei dem er den Knoten mit der kleinsten Entfernung auswählt und seine Nachbarn aktualisiert | Der Bellman-Ford-Algorithmus entspannt alle Kanten in jeder Iteration und aktualisiert den Abstand jedes Knotens, indem er alle möglichen Pfade zu diesem Knoten berücksichtigt |
| Zeitkomplexität | Der Dijkstra-Algorithmus hat eine Zeitkomplexität von O(V^2) für einen dichten Graphen und O(E log V) für einen dünn besetzten Graphen, wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten im Graphen ist. | Der Bellman-Ford-Algorithmus hat eine zeitliche Komplexität von O(VE), wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten im Diagramm ist. |
| Negative Gewichte | Der Dijkstra-Algorithmus funktioniert nicht mit Diagrammen mit negativen Kantengewichten, da er davon ausgeht, dass alle Kantengewichte nicht negativ sind. | Der Bellman-Ford-Algorithmus kann negative Kantengewichte verarbeiten und Zyklen mit negativem Gewicht im Diagramm erkennen. |
Dijkstras Algorithmus vs. Floyd-Warshall-Algorithmus
Dijkstras Algorithmus und Floyd-Warshall-Algorithmus werden beide verwendet, um den kürzesten Weg in einem gewichteten Diagramm zu finden, weisen jedoch einige wesentliche Unterschiede auf. Hier sind die Hauptunterschiede zwischen dem Dijkstra-Algorithmus und dem Floyd-Warshall-Algorithmus:
| Besonderheit: | Dijkstras | Floyd-Warshall-Algorithmus |
|---|---|---|
| Optimierung | Optimiert für die Suche nach dem kürzesten Pfad zwischen einem einzelnen Quellknoten und allen anderen Knoten in einem Diagramm mit nicht negativen Kantengewichten | Der Floyd-Warshall-Algorithmus ist für die Suche nach dem kürzesten Pfad zwischen allen Knotenpaaren in einem Diagramm optimiert. |
| Technik | Der Dijkstra-Algorithmus ist ein Single-Source-Shortest-Path-Algorithmus, der einen Greedy-Ansatz verwendet und den kürzesten Pfad vom Quellknoten zu allen anderen Knoten im Diagramm berechnet. | Der Floyd-Warshall-Algorithmus hingegen ist ein Algorithmus für den kürzesten Pfad aller Paare, der dynamische Programmierung verwendet, um den kürzesten Pfad zwischen allen Knotenpaaren im Diagramm zu berechnen. |
| Zeitkomplexität | Der Dijkstra-Algorithmus hat eine Zeitkomplexität von O(V^2) für einen dichten Graphen und O(E log V) für einen dünn besetzten Graphen, wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten im Graphen ist. | Der Floyd-Warshall-Algorithmus hingegen ist ein Algorithmus für den kürzesten Pfad aller Paare, der dynamische Programmierung verwendet, um den kürzesten Pfad zwischen allen Knotenpaaren im Diagramm zu berechnen. |
| Negative Gewichte | Der Dijkstra-Algorithmus funktioniert nicht mit Diagrammen mit negativen Kantengewichten, da er davon ausgeht, dass alle Kantengewichte nicht negativ sind. | Der Floyd-Warshall-Algorithmus hingegen ist ein Algorithmus für den kürzesten Pfad aller Paare, der dynamische Programmierung verwendet, um den kürzesten Pfad zwischen allen Knotenpaaren im Diagramm zu berechnen. |
Dijkstras Algorithmus vs. A*-Algorithmus
Dijkstras Algorithmus und A*-Algorithmus werden beide verwendet, um den kürzesten Weg in einem gewichteten Diagramm zu finden, weisen jedoch einige wesentliche Unterschiede auf. Hier sind die Hauptunterschiede zwischen dem Dijkstra-Algorithmus und dem A*-Algorithmus:
| Besonderheit: | A*-Algorithmus | |
|---|---|---|
| Suchtechnik | Optimiert für die Suche nach dem kürzesten Pfad zwischen einem einzelnen Quellknoten und allen anderen Knoten in einem Diagramm mit nicht negativen Kantengewichten | Der A*-Algorithmus ist ein informierter Suchalgorithmus, der eine heuristische Funktion verwendet, um die Suche zum Zielknoten zu leiten. |
| Heuristische Funktion | Der Dijkstra-Algorithmus verwendet keine heuristische Funktion und berücksichtigt alle Knoten im Diagramm. | Der A*-Algorithmus verwendet eine heuristische Funktion, die die Entfernung vom aktuellen Knoten zum Zielknoten schätzt. Diese heuristische Funktion ist zulässig, d. h. sie überschätzt niemals die tatsächliche Entfernung zum Zielknoten |
| Zeitkomplexität | Der Dijkstra-Algorithmus hat eine Zeitkomplexität von O(V^2) für einen dichten Graphen und O(E log V) für einen dünn besetzten Graphen, wobei V die Anzahl der Eckpunkte und E die Anzahl der Kanten im Graphen ist. | Die zeitliche Komplexität des A*-Algorithmus hängt von der Qualität der heuristischen Funktion ab. |
| Anwendung | Der Dijkstra-Algorithmus wird in vielen Anwendungen wie Routing-Algorithmen, GPS-Navigationssystemen und Netzwerkanalysen verwendet | . Ein*-Algorithmus wird häufig bei Pfadfindungs- und Graphtraversalproblemen verwendet, beispielsweise bei Videospielen, Robotik und Planungsalgorithmen. |
Übungsaufgaben zum Dijkstra-Algorithmus:
- Dijkstras Kürzester-Weg-Algorithmus | Gieriger Algo-7
- Dijkstras Algorithmus zur Darstellung von Adjazenzlisten | Gieriger Algo-8
- Dijkstras Algorithmus – Prioritätswarteschlangen- und Array-Implementierung
- Dijkstras Algorithmus für den kürzesten Weg unter Verwendung von Set in STL
- Dijkstras Kürzester-Weg-Algorithmus mit STL in C++
- Dijkstras Shortest-Path-Algorithmus unter Verwendung der Priority_Queue von STL
- Dijkstras Kürzester-Weg-Algorithmus unter Verwendung einer Matrix in C++
- Dijkstras Algorithmus für den kürzesten Single-Source-Pfad in einem DAG
- Dijkstras Algorithmus unter Verwendung von Fibonacci Heap
- Dijkstras Kürzester-Weg-Algorithmus für gerichtete Graphen mit negativen Gewichten
- Drucken von Pfaden im Shortest-Path-Algorithmus von Dijkstra
- Dijkstras Kürzester-Weg-Algorithmus mit Prioritätswarteschlange in Java




