Der Algorithmus von Dijkstra

Der Algorithmus von Dijkstra, der vom holländischen Computerwissenschaftler Edsger Dijkstra 1956 konzipiert ist und 1959 veröffentlicht ist, ist ein Graph-Suchalgorithmus, der die einzelne Quelle kürzestes Pfad-Problem für einen Graphen mit nichtnegativen Rand-Pfad-Kosten löst, einen kürzesten Pfad-Baum erzeugend. Dieser Algorithmus wird häufig in der Routenplanung und als ein Unterprogramm in anderen Graph-Algorithmen verwendet.

Für einen gegebenen Quellscheitelpunkt (Knoten) im Graphen findet der Algorithmus den Pfad mit niedrigsten Kosten (d. h. dem kürzesten Pfad) zwischen diesem Scheitelpunkt und jedem anderen Scheitelpunkt. Es kann auch verwendet werden, um Kosten von kürzesten Pfaden von einem einzelnen Scheitelpunkt bis einen einzelnen Bestimmungsort-Scheitelpunkt durch das Aufhören des Algorithmus zu finden, sobald der kürzeste Pfad zum Bestimmungsort-Scheitelpunkt bestimmt worden ist. Zum Beispiel, wenn die Scheitelpunkte des Graphen Städte vertreten und Rand-Pfad-Kosten Fahrentfernungen zwischen Paaren von durch eine direkte Straße verbundenen Städten vertreten, kann der Algorithmus von Dijkstra verwendet werden, um den kürzesten Weg zwischen einer Stadt und allen anderen Städten zu finden. Infolgedessen wird der kürzeste Pfad zuerst in Netzroutenplanungsprotokollen weit verwendet, am meisten namentlich IST - IST, und OSPF (Öffnen Sie Kürzesten Pfad Zuerst).

Der ursprüngliche Algorithmus von Dijkstra verwendet keine Warteschlange des Minute-Vorrangs und Läufe in O (|V). Die Idee von diesem Algorithmus wird auch eingereicht. Die Durchführung, die auf einer Warteschlange des Minute-Vorrangs gestützt ist, die durch einen Haufen von Fibonacci durchgeführt ist und in O laufend (|E + loggen |V |V), ist wegen. Das ist asymptotisch der schnellste bekannte Algorithmus des kürzesten Pfads der einzelnen Quelle für willkürliche geleitete Graphen mit unbegrenzten nichtnegativen Gewichten. (Für eine Übersicht von früheren kürzesten Pfad-Algorithmen und späteren Verbesserungen und Anpassungen, sieh: Algorithmen der kürzesten Pfade der einzelnen Quelle für geleitete Graphen mit nichtnegativen Gewichten.)

Algorithmus

Lassen Sie den Knoten, an dem wir anfangen, den anfänglichen Knoten genannt zu werden. Lassen Sie die Entfernung des Knotens Y die Entfernung vom anfänglichen Knoten bis den Algorithmus von Y. Dijkstra sein wird einige anfängliche Entfernungswerte zuteilen und wird versuchen, sie nach und nach zu verbessern.

  1. Teilen Sie jedem Knoten einen versuchsweisen Entfernungswert zu: Setzen Sie es auf die Null für unseren anfänglichen Knoten und auf die Unendlichkeit für alle anderen Knoten.
  2. Kennzeichnen Sie alle verlassenen Knoten. Setzen Sie den anfänglichen Knoten als Strom. Schaffen Sie eine Reihe die verlassenen Knoten haben den verlassenen Satz genannt, der aus allen Knoten außer dem anfänglichen Knoten besteht.
  3. Für den aktuellen Knoten, denken Sie alle seine verlassenen Nachbarn und berechnen Sie ihre versuchsweisen Entfernungen. Zum Beispiel, wenn der aktuelle Knoten A mit einer versuchsweisen Entfernung 6 gekennzeichnet wird, und der Rand, der ihn mit einem Nachbar B verbindet, Länge 2 hat, dann wird die Entfernung zu B (durch A) 6+2=8 sein. Wenn diese Entfernung weniger ist als die vorher registrierte versuchsweise Entfernung von B, dann überschreiben Sie diese Entfernung. Wenn auch ein Nachbar untersucht worden ist, wird es, wie besucht, in dieser Zeit nicht gekennzeichnet, und es bleibt im verlassenen Satz.
  4. Wenn wir getan werden, alle Nachbarn des aktuellen Knotens denkend, den aktuellen Knoten, wie besucht, kennzeichnen und es vom verlassenen Satz entfernen. Ein besuchter Knoten wird wieder nie überprüft; seine Entfernung registriert ist jetzt endgültig und minimal.
  5. Wenn der Bestimmungsort-Knoten besucht gekennzeichnet worden ist (wenn man einen Weg zwischen zwei spezifischen Knoten plant), oder wenn die kleinste versuchsweise Entfernung unter den Knoten im verlassenen Satz Unendlichkeit ist (wenn Sie ein ganzes Traversal planen), dann halten Sie an. Der Algorithmus ist fertig gewesen.
  6. Setzen Sie den verlassenen Knoten, der mit der kleinsten versuchsweisen Entfernung als der folgende "aktuelle Knoten" gekennzeichnet ist, und gehen Sie zum Schritt 3 zurück.

Beschreibung

:Note: Für die Bequemlichkeit des Verstehens gebraucht diese Diskussion die Begriffe Kreuzung, Straße und Karte - jedoch, formell sind diese Begriffe Scheitelpunkt, Rand und Graph beziehungsweise.

Nehmen Sie an, dass Sie den kürzesten Pfad zwischen zwei Kreuzungen auf einer Stadtkarte, einem Startpunkt und einem Bestimmungsort finden wollen. Die Ordnung ist begrifflich einfach: Um anzufangen, kennzeichnen Sie die Entfernung zu jeder Kreuzung auf der Karte mit der Unendlichkeit. Das wird getan, um nicht anzudeuten, dass es eine unendliche Entfernung gibt, aber zu bemerken, dass diese Kreuzung noch nicht besucht worden ist; einige Varianten dieser Methode verlassen einfach die Kreuzung unetikettiert. Jetzt, bei jeder Wiederholung, wählen Sie eine aktuelle Kreuzung aus. Für die erste Wiederholung wird die aktuelle Kreuzung der Startpunkt sein, und die Entfernung dazu (das Etikett der Kreuzung) wird Null sein. Für nachfolgende Wiederholungen (nach dem ersten) wird die aktuelle Kreuzung die nächste verlassene Kreuzung zum Startpunkt sein — das wird leicht sein zu finden.

Von der aktuellen Kreuzung, aktualisieren Sie die Entfernung zu jeder verlassenen Kreuzung, die damit direkt verbunden wird. Das wird durch die Bestimmung der Summe der Entfernung zwischen einer verlassenen Kreuzung und dem Wert der aktuellen Kreuzung, und das Wiederbeschriften der verlassenen Kreuzung mit diesem Wert getan, wenn es weniger ist als sein aktueller Wert. Tatsächlich wird die Kreuzung wiederetikettiert, wenn der Pfad dazu durch die aktuelle Kreuzung kürzer ist als die vorher bekannten Pfade. Um kürzeste Pfad-Identifizierung zu erleichtern, kennzeichnen mit Bleistift die Straße mit einem Pfeil, der zur wiederetikettierten Kreuzung hinweist, wenn Sie es/wiederetikettieren etikettieren, und alles andere löschen, die dazu hinweisen. Nachdem Sie die Entfernungen zu jeder benachbarten Kreuzung aktualisiert haben, die aktuelle Kreuzung, wie besucht, kennzeichnen und die verlassene Kreuzung mit der niedrigsten Entfernung (vom Startpunkt) - oder niedrigstes Etikett — als die aktuelle Kreuzung auswählen. Gekennzeichnete wie besuchte Knoten werden mit dem kürzesten Pfad vom Startpunkt bis es etikettiert und werden nicht wieder besucht oder darin zurückgegeben.

Setzen Sie diesen Prozess fort, die benachbarten Kreuzungen mit den kürzesten Entfernungen zu aktualisieren, dann die aktuelle Kreuzung, wie besucht, kennzeichnend und auf die nächste verlassene Kreuzung übergehend, bis Sie den Bestimmungsort, wie besucht, gekennzeichnet haben. Sobald Sie den Bestimmungsort, wie besucht, gekennzeichnet haben (wie mit jeder besuchten Kreuzung der Fall ist), haben Sie den kürzesten Pfad dazu vom Startpunkt bestimmt, und können Ihren Weg zurück im Anschluss an die Pfeile rückwärts verfolgen.

Des Zeichens ist die Tatsache, dass dieser Algorithmus keinen Versuch macht, "Erforschung" zum Bestimmungsort zu leiten, wie man erwarten könnte. Eher ist die alleinige Rücksicht in der Bestimmung der folgenden "aktuellen" Kreuzung seine Entfernung vom Startpunkt. In einem Sinn breitet sich dieser Algorithmus "äußer" vom Startpunkt aus, wiederholend jeden Knoten denkend, der in Bezug auf die kürzeste Pfad-Entfernung näher ist, bis es den Bestimmungsort erreicht. Wenn verstanden, auf diese Weise ist es klar, wie der Algorithmus notwendigerweise den kürzesten Pfad findet, jedoch kann es auch eine der Schwächen des Algorithmus offenbaren: seine Verhältnislangsamkeit in einigen Topologien.

Pseudocode

Im folgenden Algorithmus, dem Code, sucht nach dem Scheitelpunkt im Scheitelpunkt-Satz, der kleinsten Wert hat. Dieser Scheitelpunkt wird vom Satz entfernt und dem Benutzer zurückgegeben. berechnet die Länge zwischen den zwei Nachbarknoten und. Die Variable online 15 ist die Länge des Pfads vom Wurzelknoten bis den Nachbarknoten, wenn es durchgehen sollte. Wenn dieser Pfad kürzer ist als der aktuelle kürzeste Pfad, der dafür registriert ist, wird dieser aktuelle Pfad durch diesen Pfad ersetzt. Die Reihe wird mit einem Zeigestock zum Knoten "des folgenden Sprungs" auf dem Quellgraphen bevölkert, um den kürzesten Weg zur Quelle zu bekommen.

1 Funktion Dijkstra (Graph, Quelle):

2 für jeden Scheitelpunkt v im Graphen://Initialisierungen

3 dist [v]: = Unendlichkeit;//Unbekannte Entfernungsfunktion von der Quelle zu v

4 vorherige [v]: = unbestimmt;//Vorheriger Knoten im optimalen Pfad von der Quelle

5 Ende dafür;

6 dist [Quelle]: = 0;//Entfernung von der Quelle zur Quelle

7 Q: = der Satz aller Knoten im Graphen;//werden Alle Knoten im Graphen unoptimiert - so sind in Q

8, während Q nicht leer ist://Die Hauptschleife

9 u: = Scheitelpunkt in Q mit der kleinsten Entfernung in dist [];

10 wenn dist [u] = Unendlichkeit:

11 Brechung;//sind alle restlichen Scheitelpunkte von der Quelle unzugänglich

12 Ende wenn;

13 entfernen u von Q;

14 für jeden Nachbarv von u://, wohin v von Q noch nicht entfernt worden ist.

15 alt: = dist [u] + dist_between (u, v);

16, wenn alt und, wir die Suche an der Linie 13 wenn begrenzen können.

Jetzt können wir den kürzesten Pfad von zu durch die Wiederholung lesen:

1 S: = leere Folge

2 u: = nehmen ins Visier

3, während vorherig, wird [u] definiert:

4 Einsatz u am Anfang S

5 u: = vorherig [u]

6 Ende während;

Jetzt ist Folge die Liste von Scheitelpunkten, die einen der kürzesten Pfade von zu, oder die leere Folge einsetzen, wenn kein Pfad besteht.

Ein allgemeineres Problem würde sein, alle kürzesten Pfade zwischen und zu finden (es könnte mehrere verschiedene derselben Länge geben). Dann, anstatt nur einen einzelnen Knoten in jedem Zugang von zu versorgen, würden uns alle Knoten versorgen, die die Entspannungsbedingung befriedigen. Zum Beispiel, wenn beide und dazu in Verbindung stehen und sie beide auf verschiedenen kürzesten Pfaden durch lügen (weil die Rand-Kosten dasselbe in beiden Fällen sind), dann würden wir beide und dazu hinzufügen. Wenn der Algorithmus vollendet, wird Datenstruktur wirklich einen Graphen beschreiben, der eine Teilmenge des ursprünglichen Graphen mit einigen entfernten Rändern ist. Sein Schlüsseleigentum wird darin bestehen, dass, wenn der Algorithmus mit einem Startknoten geführt wurde, dann wird jeder Pfad von diesem Knoten bis jeden anderen Knoten im neuen Graphen der kürzeste Pfad zwischen jenen Knoten im ursprünglichen Graphen und alle Pfade dieser Länge vom ursprünglichen Graphen sein, im neuen Graphen da sein wird. Um dann wirklich alle diese kurzen Pfade zwischen zwei gegebenen Knoten zu finden, würden wir einen Pfad-Entdeckungsalgorithmus auf dem neuen Graphen wie Tiefensuche verwenden.

Laufzeit

Ein oberer, der der Laufzeit des Algorithmus von Dijkstra auf einem Graphen mit Rändern und Scheitelpunkten gebunden ist, kann als eine Funktion und das Verwenden Großer-O Notation ausgedrückt werden.

Weil jede Durchführung des Scheitelpunkts untergegangen ist, ist die Laufzeit, wo und Zeiten sind, musste Abnahme-Schlüssel und Extrakt-Minimum-Operationen im Satz beziehungsweise durchführen.

Die einfachste Durchführung des Algorithmus von Dijkstra versorgt Scheitelpunkte des Satzes in einer gewöhnlichen verbundenen Liste oder Reihe, und Extrakt-Minimum davon ist einfach eine geradlinige Suche durch alle Scheitelpunkte darin. In diesem Fall ist die Laufzeit.

Für spärliche Graphen, d. h. Graphen mit weit weniger als Ränder, kann der Algorithmus von Dijkstra effizienter durch die Speicherung des Graphen in der Form von Angrenzen-Listen und das Verwenden eines binären Haufens, die Paarung des Haufens oder Haufens von Fibonacci als eine Vorzugswarteschlange durchgeführt werden, um Extrahieren-Minimum effizient durchzuführen. Mit einem binären Haufen verlangt der Algorithmus Zeit (der durch O (| E | Klotz | V |) beherrscht wird, annehmend, dass der Graph verbunden wird). Um O (|V |) zu vermeiden, schauen im Schritt des Abnahme-Schlüssels auf einer Vanille binärer Haufen, es ist notwendig, einen ergänzenden Index aufrechtzuerhalten, der jeden Scheitelpunkt zum Index des Haufens kartografisch darstellt (und es aktuell zu halten, als sich Vorzugswarteschlange ändert), es lassend, stattdessen Zeit in Anspruch nehmen. Der Fibonacci Haufen verbessert das dazu.

Bemerken Sie, dass für Geleitete acyclic Graphen es möglich ist, kürzeste Pfade von einem gegebenen Startscheitelpunkt in der geradlinigen Zeit, durch die Verarbeitung der Scheitelpunkte in einer topologischen Ordnung und das Rechnen der Pfad-Länge für jeden Scheitelpunkt zu finden, um die minimale über einigen seiner eingehenden Ränder erhaltene Länge zu sein.

Zusammenhängende Probleme und Algorithmen

Die Funktionalität des ursprünglichen Algorithmus von Dijkstra kann mit einer Vielfalt von Modifizierungen erweitert werden. Zum Beispiel manchmal ist es wünschenswert, Lösungen zu präsentieren, die weniger sind als mathematisch optimal. Um eine aufgereihte Liste von less-optimal Lösungen zu erhalten, wird die optimale Lösung zuerst berechnet. Ein einzelner Rand, der in der optimalen Lösung erscheint, wird vom Graphen entfernt, und die optimale Lösung dieses neuen Graphen wird berechnet. Jeder Rand der ursprünglichen Lösung wird der Reihe nach und ein neuer berechneter kürzester Pfad unterdrückt. Die sekundären Lösungen werden dann aufgereiht und nach der ersten optimalen Lösung präsentiert.

Der Algorithmus von Dijkstra ist gewöhnlich der Arbeitsgrundsatz hinter mit der Verbindung staatlichen Routenplanungsprotokollen, OSPF und IST - ist die allgemeinsten.

Verschieden vom Algorithmus von Dijkstra kann der Algorithmus von Ford des Öffentlichen Ausrufers auf Graphen mit negativen Rand-Gewichten verwendet werden, so lange der Graph keinen negativen Zyklus enthält, der vom Quellscheitelpunkt s erreichbar ist. (Die Anwesenheit solcher Zyklen bedeutet, dass es keinen kürzesten Pfad gibt, da das Gesamtgewicht niedriger jedes Mal wird, wenn der Zyklus überquert wird.)

Der A* Algorithmus ist eine Generalisation des Algorithmus von Dijkstra, der die Größe des Subgraphen einschränkt, der erforscht werden muss, wenn Zusatzinformation verfügbar ist, der einen niedrigeren zur Verfügung stellt, hat zur "Entfernung" zum Ziel gebunden. Diese Annäherung kann von der Perspektive der geradlinigen Programmierung angesehen werden: Es gibt ein natürliches geradliniges Programm, um kürzeste Pfade zu schätzen, und Lösungen seines geradlinigen Doppelprogramms sind ausführbar, wenn, und nur wenn sie einen konsequenten heuristischen bilden (grob da sprechend, unterscheidet sich die Zeichen-Vereinbarung von Ort zu Ort in der Literatur). Das ausführbar Doppel-/konsequent heuristisch definiert nichtnegative reduzierte Kosten, und A* führt im Wesentlichen den Algorithmus von Dijkstra mit diesen reduzierten Kosten. Wenn der Doppel-die schwächere Bedingung der Annehmbarkeit befriedigt, dann ist A* stattdessen mit dem Algorithmus von Ford des Öffentlichen Ausrufers verwandter.

Der Prozess, der dem Algorithmus von Dijkstra unterliegt, ist dem gierigen im Algorithmus von Prim verwendeten Prozess ähnlich. Der Zweck von Prim ist, einen minimalen Überspannen-Baum zu finden, der alle Knoten im Graphen verbindet; Dijkstra ist mit nur zwei Knoten beschäftigt. Prim bewertet das Gesamtgewicht des Pfads vom Startknoten, nur des individuellen Pfads nicht.

Dynamische Programmierperspektive

Aus einem dynamischen Programmiergesichtspunkt ist der Algorithmus von Dijkstra ein aufeinander folgendes Annäherungsschema, das die dynamische programmierende funktionelle Gleichung für das kürzeste Pfad-Problem durch die reichende Methode löst.

Tatsächlich, die Erklärung von Dijkstra der Logik hinter dem Algorithmus, nämlich

ist ein Paraphrasieren des berühmten Grundsatzes des öffentlichen Ausrufers von Optimality im Zusammenhang des kürzesten Pfad-Problems.

Siehe auch

Referenzen

Außenverbindungen

C# C#

Finanzkapital / Subwoofer
Impressum & Datenschutz