• Keine Ergebnisse gefunden

Suchen von k¨ urzesten Wegen mit dem Dijkstra-Algorithmus

Im Dokument Programmiertechniken (NF) (Seite 80-83)

6. List-Comprehensions 71

7.3. Suchen von k¨ urzesten Wegen mit dem Dijkstra-Algorithmus

Um einen k¨urzesten Wegen in einem Graphen zu suchen, werden die Kantenbeschriftun-gen als Gewichte interpretiert. die dr¨ucken also aus, wie viel Zeit, Entfernung oder Geld es kostet, auf einer Kante von einem Knoten zum anderen zu kommen. Im Gegensatz zur Tiefen- bzw. Breitensuche sind wir hier also noch an g¨unstigsten Wegen (unter Ber¨ uck-sichtigung der Kantengewichte) interessiert und nicht daran, ob es ¨uberhaupt einen Weg gibt. Außerdem wollen wir auch m¨oglichst nicht alle Knoten des Graphen besuchen. Es w¨are ja unsinnig, den Knoten M¨unchen zum Finden des k¨urzesten Weges zu besuchen, wenn man von Kiel nach Neum¨unster fahren m¨ochte.

Der einfachste Ansatz, um den k¨urzesten Weg zwischen zwei Knoten zu finden, ist es, alle Wege zwischen diesen beiden Knoten auszuprobieren, die Entfernungen zwischen den einzelnen Knoten zu jedem Weg aufzusummieren und dann den Weg mit der kleinsten Gesamtentfernung zu nehmen. hierbei w¨urde man aber eben auch eine Weg ¨uber M¨unchen betrachten, was man f¨ur einen effizienteren Algorithmus nat¨urlich vermeiden m¨ochte.

Wenn man als Mensch einen “k¨urzesten” Weg zwischen zwei Orten unter Verwendung einer Landkarte sucht, orientiert man sich in der Regel an der r¨aumlichen Lage der Orte und geht davon aus, dass die Luftlinie nah am k¨urzesten Reiseweg liegt. Solch eine Infor-mation verwenden moderne Navigationsger¨ate (in abgewandelter Form) tats¨achlich auch.

Die ersten Ans¨atze, welche wir hier aber auch betrachten werden, verwenden solche Infor-mationen allerdings nicht. Wir orientieren uns ausschließlich an den Gewichten der Kanten, welche von einem zum anderen Knoten f¨uhren.

Schon 1959 entwickelte der niederl¨andische Informatiker Edsger Wybe Dijkstra den sp¨ater nach ihm benannten Dijkstra-Algorithmus zum Finden k¨urzester Wege in Graphen, der noch heute mit Zusatzinforamtionen optimiert (z.B. Speichern von Entfernungen zwischen Uberknoten wie Automahnkreuzen als Zusatzinforamtionen) in Navigationsger¨¨ aten ver-wendet wird.

Die Grundlegende Idee des Dijkstra Algorithmus ist, dass man von Startknoten ausgehende alle weiteren Knoten in einer Art gewichteten Breitensuche betrachtet und hierbei sich immer die k¨urzesten Verbindungen zu den entsprechenden anderen Knoten merkt.

Der Dijkstra-Algorithmus beinhaltet folgende Arbeitsschritte:

1. Weise dem Startknoten die Entfernung 0 zu und f¨uge ihn in die ToDo-Liste ein 2. Solange noch Knoten in der ToDo-Liste sind, betrachte den Knoten mit der kleinsten

Entfernung und nimm ihn aus der ToDo-Liste heraus.

a) schreibe ihn in die Liste der besuchten Knoten

b) verwende seine Entfernung als k¨urzesten Weg und beende c) Fallunterscheidung:

• falls der aktuelle Knoten der Endknoten ist, hast du den k¨urzesten Weg gefunden

• sonst gehe die Liste seiner Nachbarknoten durch. Falls er noch nicht be-sucht wurde, verfahre wie folgt:

i. addiere sein Kantengewicht mit dem aktuellen k¨urzesten Weg ii. Fallunterscheidung:

– falls er noch nicht in der ToDo-Liste steht, f¨uge ihn mit der aktuellen Entfernung hinzu

– sonst vergleiche die aktuelle Entfernung mit der Entfernung in der Liste und aktualisiere diese, falls die berechnete Enfernung k¨urzer ist Wenn der Startknoten mit dem Endknoten verbunden ist, wird der Algorithmus irgendwann durch Schritt b) terminieren. Wenn die beiden nicht miteinander verbunden ist, wird der Algorithmus abbrechen sobald die ToDo-Liste leer ist.

7.3.1. Beispiel

Anhand der folgenden Karte von Schleswig Holstein soll der k¨urzeste Weg von Rendburg (RD) nach L¨ubeck (HL) gefunden werden. Ob dies wirklich der der k¨urzeste Weg ist, wollen wir hier nicht weiter diskutieren. M¨oglicherweise stimmen die Entfernungen unserer fiktiven nicht mit den wirklichen Entfernungen ¨uberein. Die Abbildung zeigt eine grafische Darstellung des Graphen, der durch die Kanten und Knoten der csv-Datei sh−map.csv definiert ist.

HL SE

PL ¨O NMS

PRE KI

RD 38

40 34 19

30 37 35

14

35

38 35

Schritte bereits besuchte Orte ToDo-Liste der erreichbaren Orte

Wir haben also nach 7 Schritten die k¨urzesten Entfernung von RD nach HL berechnet.

Hierbei kam es aber nicht zu einem Aktualisierungsschritt. Um diesen zu verstehen, be-trachten wir ein anderes Beispiel:

Wir suchen den k¨urzesten Weg von A nach D. Es ergeben sich die folgenden Schritte:

Schritte bereits besuchte Orte ToDo-Liste der erreichbaren Orte

1. [] [(0, A)]

Besonders interessant sind die Schritte 3 und 4. In Schritt 3 besuchen wir den Knoten B. Seine Nachfolger sind C und D. Der Weg zu C ¨uber den Knoten B h¨atte die L¨ange 8. Deshalb bleibt die Entfernung zum Knoten C unver¨andert bei 4, was k¨urzer ist. Der Nachfolger D kommt noch nicht in der ToDo-Liste vor. Er wird also mit der Entfernung 9 eingetragen. In Schritt 4 wird dann der Knoten C als n¨achster noch nicht untersuchter Knoten betrachtet. Er hat die noch nicht besuchten Knoten E und D. F¨ur E betr¨agt die Entfernung ¨uber C 7, weshalb E mit der Entfernung 5 unver¨andert bleibt. F¨ur D betr¨agt die Entfernung nun aber 8, was eine k¨urzere Entfernung ist, als die vorher ¨uber B gefundene Entfernung (9) ist. Somit wird die bisher bekannte k¨urzestes Verbindung von A zu D von 9 auf 8 aktualisiert.

Solch ein Schritt ist auch in der Schleswig-Holstein-Karte m¨oglich. Als ¨Ubung sollten Sie nach solchen Situationen suchen.

Bis jetzt berechnet der Dijkstra-Algorithmus lediglich die “k¨urzeste” Entfernung zwischen zwei Knoten eines Graphen. Der konkrete Pfad (also eine Liste von zu besuchenden Knoten) fehlt noch. Diesen kann man aber einfach w¨ahrend der Berechnung protokollieren, was als Ubungsaufgabe realisiert werden soll.¨

7.3.2. Implementierung

F¨ur die Implementierung m¨ussen wir im wesentlichen die beiden Listen ToDo-Liste und Liste bereits besuchter Knoten realisieren. F¨ur die bereits besuchten Knoten ist sinnvoll eine effiziente Mengen-Implementierung zu w¨ahlen, da wir immer wieder f¨ur alle Nachbarknoten nachschlagen m¨ussen, ob diese bereits besucht wurde. Die ToDo-Liste der erreichbaren Orte implementieren eigene Klasse, welche eine sortierte Liste aller Gewicht-Ort-Paare als Attribut vorh¨alt. dies ist nicht die effizienteste Implementierung, da sowohl das sortierte Einf¨ugen als auch das Nachschlagen von bereits vorhandenen Knoten linear in der L¨ange der ToDo-Liste ist. Dennoch soll uns dies hier ausreichen. Effizientere Darstellung findet ihr in weitergehenden Literatur, welche ihr sehr gut ausgehend von dem Wikipedia-Artikel zum Dijkstra-Algorithmus finden k¨onnt.

Der Code steht auf der Web-Seite der Vorlesung zum download bereit.

Im Dokument Programmiertechniken (NF) (Seite 80-83)