Hallo. In meinem Letzten Beitrag (Beitrag "Javascript Verkehrsleitsystem") wurde mir geraten, für das Finden des kürzesten Weges zwischen zwei Punkten den A*-Algorithmus zu verwenden. Nach einigen Recherchen lernte ich jedoch den Dijkstra-Algorithmus kennen, der mir nicht nur verständlicher, sondern auch einfacher erscheint, da nicht berechnet werden muss, wie wahrscheinlich es ist, dass ein bestimmter Pfad eher zum Ziel führt als andere. Ich fand nach einiger Suche Code für JavaScript, der Programmiersprache, in der ich den Algorithmus implementieren möchte, auf folgender Seite: https://www.tutorialspoint.com/Dijkstra-s-algorithm-in-Javascript Jedoch gibt dieser die kürzeste Entfernung zu allen weiteren Knoten von einem Startknoten aus an. Ich benötige jedoch zum einen die Entfernung zu einem bestimmten Knoten, zum anderen möchte ich wissen, welchen Pfad das Programm errechnet hat. Wie müsste ich den Code umschreiben? Wird in der "while (!pq.isEmpty())"-Schleife geprüft, ob der Ziel-Knoten schon erreicht ist? Zu Beginn des Programms würde ich ein Array initialisieren ("let pfad = [];"), welches ebenfalls ausgegeben wird und den "zu gehenden" Pfad angibt. In welcher Schleife werden dann die Knoten des Pfades diesem Array hinzugefügt? Verzeiht die etwas plumpe Grußformel und Verabschiedung. Was kreative Begrüßungen und Verabschiedungen angeht, bin ich (zum Glück?) kein Profi. Viele Grüße und Dank für jede hilfreiche Antwort Ernst
Ernst H. schrieb: > Wie müsste ich den Code umschreiben? Wird in der "while > (!pq.isEmpty())"-Schleife geprüft, ob der Ziel-Knoten schon erreicht > ist? https://de.wikipedia.org/wiki/Vorrangwarteschlange
1) Du prüfst einfach ab ob aus "pq" dein Zielknoten herausgenommen wird. In dem Moment kannst du den Algorithmus vorzeitig terminieren: direkt nach der Zeile let minNode = pq.dequeue(); machst du: if minNode.node == "Zielknoten" { break; } 2) Um den Pfad zu rekonstruieren musst du nur "prev" nutzen. prev speichert den Vorgängerknoten des kürzesten Pfades. Das heißt du fängst beim Zielknoten an prev auszuwerten und hangelst dich so rückwärts durch den kürzesten Pfad bis du irgendwann beim Startknoten angekommen bist. Noch ein Hinweis. Dijkstra funktioniert nur mit nichtnegativen (>=0) Kantengewichten korrekt (liefert den kürzesten Pfad).
:
Bearbeitet durch User
In Pseudocode könnte das so aussehen:
1 | function reconstruct_path(prev: Array, Startknoten, Zielknoten) { |
2 | let curNode = Zielknoten; |
3 | let Pfad : Array = [Zielknoten]; |
4 | |
5 | while curNode != Startknoten { |
6 | //ist ein Vorgänger für diesen Knoten hinterlegt? |
7 | //wenn nicht dann gibt es keinen Pfad vom Start- zum Zielknoten |
8 | if curNode != null { |
9 | curNode = prev[curNode]; |
10 | Pfad.push(curNode); |
11 | } else { |
12 | throw new Exception("Es gibt keinen Pfad vom Startknoten zum Zielknoten"); |
13 | } |
14 | } |
15 | |
16 | //bei Bedarf den Pfad umdrehen |
17 | return Pfad.reverseArray(); |
18 | } |
Theoretisch reicht es den else Zweig
1 | } else { |
2 | throw new Exception("Es gibt keinen Pfad vom Startknoten zum Zielknoten"); |
3 | } |
genau einmal für den Zielknoten am Anfang (vor der Schleife) auszuführen. Denn wenn dieser Knoten einen Vorgänger hat muss der Algorithmus vom Startknoten aus irgendwann dort hingekommen sein. Es gibt also einen Pfad. So kann man den Algorithmus etwas optimieren...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.