Ich habe einige Nachforschungen angestellt, und mir scheint ein kleiner Teil dieses Algorithmus zu fehlen. Ich verstehe, wie eine Breitensuche funktioniert, aber ich verstehe nicht, wie genau sie mich zu einem bestimmten Pfad bringt, anstatt mir nur zu sagen, wohin jeder einzelne Knoten gehen kann. Ich denke, der einfachste Weg, meine Verwirrung zu erklären, ist ein Beispiel:
Nehmen wir zum Beispiel an, ich habe ein Diagramm wie das folgende:
Und mein Ziel ist es, von A nach E zu kommen (alle Kanten sind ungewichtet).
Ich fange bei A an, weil das mein Ursprung ist. Ich stelle A in die Warteschlange, gefolgt von der sofortigen Warteschlange A und der Erkundung. Dies ergibt B und D, da A mit B und D verbunden ist. Ich stelle also sowohl B als auch D in die Warteschlange.
Ich stelle B in die Warteschlange und erkunde es und stelle fest, dass es zu A (bereits erforscht) und C führt, also stelle ich C in die Warteschlange. Dann stelle ich D in die Warteschlange und stelle fest, dass es zu E führt, meinem Ziel. Ich stelle dann C in die Warteschlange und stelle fest, dass es auch zu E führt, meinem Ziel.
Ich weiß logischerweise, dass der schnellste Pfad A-> D-> E ist, aber ich bin mir nicht sicher, wie genau die Breitensuche hilft - wie sollte ich Pfade so aufzeichnen, dass ich nach Abschluss die Ergebnisse analysieren und sehen kann dass der kürzeste Weg A-> D-> E ist?
Beachten Sie außerdem, dass ich eigentlich keinen Baum verwende, sodass es keine "übergeordneten" Knoten gibt, sondern nur untergeordnete.
Antworten:
Technisch gesehen können Sie mit der Breitensuche (BFS) selbst nicht den kürzesten Pfad finden, einfach weil BFS nicht nach einem kürzesten Pfad sucht: BFS beschreibt eine Strategie für die Suche in einem Diagramm, sagt jedoch nicht, dass Sie danach suchen müssen etwas Besonderes.
Der Dijkstra-Algorithmus passt BFS an, damit Sie kürzeste Pfade aus einer Hand finden können.
Um den kürzesten Pfad vom Ursprung zu einem Knoten abzurufen, müssen Sie für jeden Knoten im Diagramm zwei Elemente verwalten: den aktuell kürzesten Abstand und den vorhergehenden Knoten im kürzesten Pfad. Anfangs sind alle Entfernungen auf unendlich und alle Vorgänger auf leer gesetzt. In Ihrem Beispiel setzen Sie den Abstand von A auf Null und fahren dann mit dem BFS fort. Bei jedem Schritt prüfen Sie, ob Sie die Entfernung eines Nachkommen verbessern können, dh die Entfernung vom Ursprung zum Vorgänger plus die Länge der Kante, die Sie untersuchen, ist geringer als die derzeit beste Entfernung für den betreffenden Knoten. Wenn Sie die Entfernung verbessern können, stellen Sie den neuen kürzesten Pfad ein und merken Sie sich den Vorgänger, über den dieser Pfad erfasst wurde. Wenn die BFS-Warteschlange leer ist, wählen Sie einen Knoten aus (in Ihrem Beispiel E) und durchlaufen Sie seine Vorgänger zurück zum Ursprung.
Wenn dies etwas verwirrend klingt, hat Wikipedia einen schönen Pseudocode-Abschnitt zum Thema.
quelle
Wie oben erwähnt, kann BFS nur verwendet werden, um den kürzesten Pfad in einem Diagramm zu finden, wenn:
Es gibt keine Schleifen
Alle Kanten haben das gleiche Gewicht oder kein Gewicht.
Um den kürzesten Weg zu finden, müssen Sie nur von der Quelle aus starten und eine umfassende erste Suche durchführen und anhalten, wenn Sie Ihren Zielknoten gefunden haben. Das einzige zusätzliche, was Sie tun müssen, ist ein Array vor [n], in dem der vorherige Knoten für jeden besuchten Knoten gespeichert wird. Der vorherige der Quelle kann null sein.
Um den Pfad zu drucken, durchlaufen Sie einfach das vorherige [] Array von der Quelle bis zum Ziel und drucken die Knoten. DFS kann auch verwendet werden, um unter ähnlichen Bedingungen den kürzesten Pfad in einem Diagramm zu finden.
Wenn der Graph jedoch komplexer ist und gewichtete Kanten und Schleifen enthält, benötigen wir eine komplexere Version von BFS, dh den Dijkstra-Algorithmus.
quelle
To print the path, simple loop through the previous[] array from source till you reach destination.
Der vorherige Quellcode ist jedoch null. Ich denke, was du gemeint hast ist ,backtrace from destination using the previous array until you reach the source
.Aus dem Tutorial hier
quelle
Ich habe 3 Tage verschwendet und
letztendlich eine Grafikfrage gelöst,
die zum
Finden der kürzesten Entfernung
mit BFS verwendet wurde
Möchten Sie die Erfahrung teilen.
Ich habe 3 Tage verloren, als ich alle oben genannten Alternativen ausprobiert habe und immer wieder überprüft und erneut überprüft habe, ob
sie nicht das Problem sind.
(Versuchen Sie, Zeit damit zu verbringen, nach anderen Problemen zu suchen, wenn Sie keine Probleme mit den oben genannten 5 finden.)
Weitere Erklärung aus dem Kommentar unten:
Angenommen, oben ist Ihr Diagramm
nach unten.
Für A sind die Adjazenzen B & C.
Für B sind die Adjazenten D & E.
Für C sind die Adjazenzen F & G.
Angenommen, der Startknoten ist A.
Wenn Sie A, B und C erreichen, beträgt die kürzeste Entfernung von A zu B & C 1
Wenn Sie D oder E bis B erreichen, beträgt die kürzeste Entfernung zu A & D 2 (A-> B-> D).
in ähnlicher Weise ist A-> E 2 (A-> B-> E)
auch A-> F & A-> G ist 2
Also, anstatt 1 Abstand zwischen Knoten, wenn es 6 ist, dann multiplizieren Sie einfach die Antwort mit 6
Beispiel,
wenn Abstand zwischen jedem 1 ist, dann ist A-> E 2 (A-> B-> E = 1 + 1 )
Wenn der Abstand zwischen den beiden 6 beträgt, beträgt A-> E 12 (A-> B-> E = 6 + 6).
Ja, bfs kann jeden Pfad nehmen,
aber wir berechnen für alle Pfade
Wenn Sie von A nach Z gehen müssen, fahren wir alle Pfade von A zu einem Zwischen-I. Da es viele Pfade gibt, verwerfen wir alle bis auf den kürzesten Pfad bis I und fahren dann mit dem kürzesten Pfad bis zum nächsten Knoten J fort
, wenn Es gibt mehrere Pfade von I nach J, wir nehmen nur ein kürzestes
Beispiel,
nehmen an,
A -> I wir haben Abstand 5
(SCHRITT) nehmen an, I -> J wir haben mehrere Pfade mit den Abständen 7 und 8, da 7 am kürzesten ist
wir nehmen A -> J als 5 (A-> I am kürzesten) + 8 (am kürzesten jetzt) = 13,
also ist A-> J jetzt 13,
wir wiederholen jetzt oben (SCHRITT) für J -> K und so weiter, bis wir bekommen bis Z.
Lesen Sie diesen Teil zwei- oder dreimal und zeichnen Sie auf Papier. Sie werden sicher das bekommen, was ich sage, viel Glück
quelle
Basierend auf acheron55 Antwort gab ich eine mögliche Implementierung hier .
Hier ist eine kurze Zusammenfassung davon:
Sie müssen lediglich den Pfad verfolgen, über den das Ziel erreicht wurde. Eine einfache Möglichkeit, dies zu tun, besteht darin, in den
Queue
gesamten Pfad zu pushen, der zum Erreichen eines Knotens verwendet wird, und nicht in den Knoten selbst.Dies hat den Vorteil, dass die Warteschlange nach Erreichen des Ziels den Pfad enthält, der zum Erreichen des Ziels verwendet wird.
Dies gilt auch für zyklische Diagramme, bei denen ein Knoten mehr als ein übergeordnetes Element haben kann.
quelle
Die folgende Lösung funktioniert für alle Testfälle.
quelle