|
| 1 | +# Dijkstra-Algorithmus |
| 2 | + |
| 3 | +_Lies dies in anderen Sprachen:_ |
| 4 | +[_English_](README.md), |
| 5 | +[_한국어_](README.ko-KR.md), |
| 6 | +[_日本語_](README.ja-JP.md), |
| 7 | +[_简体中文_](README.zh-CN.md), |
| 8 | +[_繁體中文_](README.zh-TW.md), |
| 9 | +[_Українська_](README.uk-UA.md), |
| 10 | +[_Español_](README.es-ES.md), |
| 11 | +[_Français_](README.fr-FR.md), |
| 12 | +[_Deutsch_](README.de-DE.md), |
| 13 | +[_עברית_](README.he-IL.md) |
| 14 | + |
| 15 | +Der Dijkstra-Algorithmus ist ein Algorithmus zur Bestimmung der kürzesten Wege zwischen Knoten in einem Graphen, der beispielsweise Straßennetze darstellen kann. |
| 16 | + |
| 17 | +Der Algorithmus existiert in vielen Varianten; die ursprüngliche Version von Dijkstra fand den kürzesten Weg zwischen zwei Knoten, aber eine gebräuchlichere Variante fixiert einen einzelnen Knoten als „Quellknoten“ und findet die kürzesten Wege von dieser Quelle zu allen anderen Knoten im Graphen. Das Ergebnis ist ein sogenannter „kürzester-Wege-Baum“ (Shortest-Path Tree). |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +Der Dijkstra-Algorithmus findet den kürzesten Weg zwischen `a` und `b`. |
| 22 | +Er wählt den unbesuchten Knoten mit der kleinsten aktuellen Entfernung, |
| 23 | +berechnet die Distanzen zu jedem unbesuchten Nachbarn über diesen Knoten |
| 24 | +und aktualisiert die Entfernung des Nachbarn, wenn sie kleiner ist. |
| 25 | +Nachdem alle Nachbarn überprüft wurden, wird der Knoten als besucht markiert (rot dargestellt). |
| 26 | + |
| 27 | +## Praktische Anwendungen des Dijkstra-Algorithmus |
| 28 | + |
| 29 | +- GPS- und Navigationssysteme |
| 30 | +- Optimierung von Routen im öffentlichen Verkehr und im Flugverkehr |
| 31 | +- Internet-Routing (OSPF-, IS-IS-Protokolle) |
| 32 | +- Optimierung von Netzwerkverkehr und Latenzzeiten |
| 33 | +- Pfadsuche in Computerspielen (kürzester Weg auf Karten) |
| 34 | +- Routenoptimierung in Logistik und Lieferketten |
| 35 | +- Planung von Transport- und Versorgungsnetzen |
| 36 | + |
| 37 | +## Schritt-für-Schritt-Beispiel des Dijkstra-Algorithmus |
| 38 | + |
| 39 | +Nehmen wir an, wir haben einen gewichteten Graphen, bei dem jede Kante eine Distanz zwischen Knoten hat. |
| 40 | +Zum Beispiel beträgt die Entfernung zwischen Knoten `A` und `B` `7 Meter` (oder kurz `7m`). |
| 41 | + |
| 42 | +Der Algorithmus verwendet eine [Prioritätswarteschlange](../../../data-structures/priority-queue/), |
| 43 | +um immer den nächsten unbesuchten Knoten mit der kleinsten Entfernung vom Startknoten zu entnehmen. |
| 44 | + |
| 45 | +Der Startknoten hat per Definition eine Entfernung von `0m` zu sich selbst. |
| 46 | +Wir beginnen also mit diesem Knoten – er ist der einzige in der Prioritätswarteschlange zu Beginn. |
| 47 | + |
| 48 | +Die restlichen Knoten werden während der Graphdurchquerung (beim Besuchen der Nachbarn) später hinzugefügt. |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +Jeder Nachbar des aus der Warteschlange entnommenen Knotens wird überprüft, um die Entfernung vom Startpunkt zu berechnen. |
| 53 | +Zum Beispiel: Die Entfernung von `A` nach `B` beträgt `0m + 7m = 7m`. |
| 54 | + |
| 55 | +Jedes Mal, wenn wir einen neuen, noch nicht gesehenen Nachbarn besuchen, fügen wir ihn der Prioritätswarteschlange hinzu, wobei die Priorität die Distanz zum Startknoten ist. |
| 56 | + |
| 57 | +Der Knoten `B` wird mit der Priorität 7m in die Warteschlange eingefügt, um später besucht zu werden. |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +Als Nächstes besuchen wir den Nachbarn `C` von `A`. |
| 62 | +Die Entfernung vom Startknoten `A` zu `C` beträgt `0m + 9m = 9m`. |
| 63 | + |
| 64 | +Der Knoten `C` wird ebenfalls in die Prioritätswarteschlange eingefügt. |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | +Dasselbe gilt für den Knoten `F`. |
| 69 | +Die aktuelle Entfernung von `A` zu `F` ist `0m + 14m = 14m`. |
| 70 | + |
| 71 | +`F` wird in die Warteschlange eingefügt, um später besucht zu werden. |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +Nachdem alle Nachbarn des aktuellen Knotens überprüft wurden, wird dieser Knoten zur `visited`-Menge hinzugefügt. |
| 76 | +Solche Knoten werden in den nächsten Schritten nicht erneut besucht. |
| 77 | + |
| 78 | +Nun entnehmen wir aus der Prioritätswarteschlange den nächsten Knoten mit der kürzesten Distanz zur Quelle und beginnen, seine Nachbarn zu besuchen. |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +Wenn der Knoten, den wir besuchen (in diesem Fall `C`), bereits in der Warteschlange ist, |
| 83 | +bedeutet das, dass die Distanz zu ihm bereits von einem anderen Pfad (`A → C`) berechnet wurde. |
| 84 | +Wenn die aktuelle Distanz (über `A → B → C`) kürzer ist, aktualisieren wir den Wert in der Warteschlange. |
| 85 | +Ist sie länger, bleibt sie unverändert. |
| 86 | + |
| 87 | +Beim Besuch von `C` über `B` (`A → B → C`) beträgt die Distanz `7m + 10m = 17m`. |
| 88 | +Dies ist länger als die bereits gespeicherte Distanz `9m` für `A → C`. |
| 89 | +Daher ignorieren wir diesen längeren Pfad. |
| 90 | + |
| 91 | + |
| 92 | + |
| 93 | +Wir besuchen einen weiteren Nachbarn von `B`, nämlich `D`. |
| 94 | +Die Entfernung zu `D` beträgt `7m + 15m = 22m`. |
| 95 | +Da `D` noch nicht besucht wurde und nicht in der Warteschlange ist, fügen wir ihn mit der Priorität `22m` hinzu. |
| 96 | + |
| 97 | + |
| 98 | + |
| 99 | +An diesem Punkt wurden alle Nachbarn von `B` besucht, daher wird `B` zur `visited`-Menge hinzugefügt. |
| 100 | +Als Nächstes entnehmen wir aus der Warteschlange den Knoten, der dem Ursprung am nächsten ist. |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | +Wir besuchen die unbesuchten Nachbarn von `C`. |
| 105 | +Die Distanz zu `F` über `C` (`A → C → F`) beträgt `9m + 2m = 11m`. |
| 106 | +Dies ist kürzer als der bisher gespeicherte Weg `A → F` von `14m`. |
| 107 | +In diesem Fall aktualisieren wir die Distanz zu `F` auf `11m` und passen ihre Priorität in der Warteschlange an. |
| 108 | +Wir haben einen kürzeren Weg zu `F` gefunden. |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | +Dasselbe gilt für `D`. |
| 113 | +Wir haben einen kürzeren Pfad zu `D` gefunden – der Weg `A → C → D` ist kürzer als `A → B → D`. |
| 114 | +Die Distanz wird von `22m` auf `20m` aktualisiert. |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | +Alle Nachbarn von `C` wurden besucht, daher fügen wir `C` zur `visited`-Menge hinzu. |
| 119 | +Wir entnehmen den nächsten Knoten aus der Warteschlange, der `F` ist. |
| 120 | + |
| 121 | + |
| 122 | + |
| 123 | +Wir notieren die Distanz zu `E` als `11m + 9m = 20m`. |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | +Wir fügen `F` zur `visited`-Menge hinzu und entnehmen den nächsten Knoten `D`. |
| 128 | + |
| 129 | + |
| 130 | + |
| 131 | +Die Distanz zu `E` über `D` ist `20m + 6m = 26m`. |
| 132 | +Das ist länger als die bereits berechnete Distanz von `20m` über `F`. |
| 133 | +Daher verwerfen wir diesen längeren Weg. |
| 134 | + |
| 135 | + |
| 136 | + |
| 137 | +Der Knoten `D` ist jetzt besucht. |
| 138 | + |
| 139 | + |
| 140 | + |
| 141 | +Auch der Knoten `E` wurde besucht. |
| 142 | +Die Durchquerung des Graphen ist abgeschlossen. |
| 143 | + |
| 144 | + |
| 145 | + |
| 146 | +Nun kennen wir die kürzesten Distanzen von jedem Knoten ausgehend vom Startknoten `A`. |
| 147 | + |
| 148 | +In der Praxis speichert man während der Berechnungen zusätzlich die `previousVertices` (vorherige Knoten), |
| 149 | +um die genaue Reihenfolge der Knoten im kürzesten Pfad rekonstruieren zu können. |
| 150 | + |
| 151 | +Zum Beispiel ist der kürzeste Pfad von `A` nach `E`: `A → C → F → E`. |
| 152 | + |
| 153 | +## Beispielimplementierung |
| 154 | + |
| 155 | +- [dijkstra.js](./dijkstra.js) |
| 156 | + |
| 157 | +## Quellen |
| 158 | + |
| 159 | +- [Wikipedia](https://de.wikipedia.org/wiki/Dijkstra-Algorithmus) |
| 160 | +- [YouTube – Nathaniel Fan](https://www.youtube.com/watch?v=gdmfOwyQlcI&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8) |
| 161 | +- [YouTube – Tushar Roy](https://www.youtube.com/watch?v=lAXZGERcDf4&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8) |
0 commit comments