Bellman-Ford-Algorithmus: Unterschied zwischen den Versionen
Sn (Diskussion | Beiträge) K (Kategorien) |
Sn (Diskussion | Beiträge) (Link und Beispiel (noch nicht gut, darum auskommentiert)) |
||
(10 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{Thumbnailbox | |||
|INHALT={{Beispielgraph/gerichtet|BD=red|BDWT=-5}} | |||
{{ | |CAPTION=Ein Beispielgraph, in dem eine Kante negatives Gewicht hat; diese Kante ist farblich hervorgehoben. | ||
}} | }} | ||
Der [[Bellman-Ford-Algorithmus]] ist ein [[Algorithmus]], der kürzeste Wege in einem [[Graph|Graphen]] findet. Anders als der [[Dijkstra-Algorithmus]] kann der Bellman-Ford-Algorithmus jedoch auch mit negativen Kantengewichten umgehen. | Der [[Bellman-Ford-Algorithmus]] ist ein [[Algorithmus]], der [[Wegfindung|kürzeste Wege]] in einem gerichteten [[Graph|Graphen]] findet. Anders als der [[Dijkstra-Algorithmus]] kann der Bellman-Ford-Algorithmus jedoch auch mit negativen Kantengewichten umgehen. | ||
==Das Problem== | ==Das Problem== | ||
Betrachten wir den nebenstehenden Beispielgraphen, in dem eine Kante negatives Gewicht hat. Der kürzeste Weg von A nach D führt über B und hat die Länge -2. Der Dijkstra-Algorithmus würde aber den Weg über C präferieren, der die Länge 3 hat. Der Dijkstra-Algorithmus ist nämlich [[greedy]] und betrachtet immer nur die nächstbeste Kante mit minimalem Gewicht. Bei Graphen mit ausschließlich positiven Kantengewichten ist das kein Problem, da die Gesamtlänge eines Weges immer nur größer werden kann. Bei Graphen, in denen auch negative Kantengewichte vorkommen, dagegen schon, da es hier auch vorteilhaft sein kann, zunächst größere Kantengewichte in Kauf zu nehmen, wenn diese später durch negative Kantengewichte ausgeglichen werden können. | Betrachten wir den nebenstehenden Beispielgraphen, in dem eine Kante negatives Gewicht hat. Der kürzeste Weg von A nach D führt über B und hat die Länge -2. Der Dijkstra-Algorithmus würde aber den Weg über C präferieren, der die Länge 3 hat. Der Dijkstra-Algorithmus ist nämlich [[Greedy-Algorithmus|greedy]] und betrachtet immer nur die nächstbeste Kante mit minimalem Gewicht. Bei Graphen mit ausschließlich positiven Kantengewichten ist das kein Problem, da die Gesamtlänge eines Weges immer nur größer werden kann. Bei Graphen, in denen auch negative Kantengewichte vorkommen, dagegen schon, da es hier auch vorteilhaft sein kann, zunächst größere Kantengewichte in Kauf zu nehmen, wenn diese später durch negative Kantengewichte ausgeglichen werden können. | ||
==Der Algorithmus== | ==Der Algorithmus== | ||
Zeile 37: | Zeile 20: | ||
Der Algorithmus läuft folgendermaßen ab: | Der Algorithmus läuft folgendermaßen ab: | ||
# Zu Beginn des Algorithmus wird für jeden Knoten <code>k</code> die <code>Distanz[k]</code> auf <math>\infty</math> und der <code>Vorgänger[k]</code> auf <code>[[null]]</code> gesetzt, außer für <code>s</code>, dessen Distanz auf 0 gesetzt wird. | |||
# Wiederhole <code>n-1</code> Mal: | |||
## Prüfe für jede Kante <code>x—y</code>: | |||
### Ist <code>Distanz[x]</code> + Kantenlänge <code>x—y</code> < <code>Distanz[y]</code>? | |||
#### Falls ja, setze <code>Distanz[y]</code> := <code>Distanz[x]</code> + Kante <code>x—y</code>… | |||
#### … und setze <code>Vorgänger[y]</code> := <code>x</code> | |||
# Zuletzt wird nochmal durch alle Kanten durchiteriert und für jede Kante <code>x—y</code> dieselbe Bedingung geprüft: | |||
## Ist <code>Distanz[x]</code> + Kante <code>x—y</code> < <code>Distanz[y]</code>? | |||
### Falls ja, dann enthält der Graph einen Kreis negativer Länge. In diesem Fall können durch wiederholtes Durchlaufen dieses Kreises beliebig kurze Wege erzeugt werden und es kann keine kürzesten Wege geben. | |||
### Falls nein, sind die kürzesten Wege gefunden und die Distanzen und Vorgänger werden zurückgegeben. | |||
== Beispiel == | |||
<!-- | |||
=== Ohne einen Kreis negativer Länge === | |||
Betrachten wir den oben abgebildeten Graphen mit der negativen Kante. | |||
{| class="wikitable | |||
|- | |||
! Schritt | |||
! <code>distance</code> | |||
! <code>previous</code> | |||
! Wdh.-Zähler | |||
! <math>v</math> | |||
! <math>u \rightarrow v</math> | |||
|- | |||
| 1 | |||
| [A: 0, B: <math>\infty</math>, C: <math>\infty</math>, D: <math>\infty</math>, E: <math>\infty</math>] | |||
| [A: null, B: null, C: null, D: null, E: null] | |||
| | |||
| | |||
| | |||
|- | |||
| 2 | |||
| | |||
| | |||
| 0 | |||
| | |||
| | |||
|- | |||
| 2.1 | |||
| | |||
| | |||
| | |||
| | |||
| <math>A\rightarrow B</math> | |||
|- | |||
| 2.1.1 | |||
| [A: 0, B: 3, C: <math>\infty</math>, D: <math>\infty</math>, E: <math>\infty</math>] | |||
| | |||
| | |||
| | |||
| | |||
|- | |||
| 12 | |||
| | |||
| [A: null, B: A, C: null, D: null, E: null] | |||
| | |||
| | |||
| | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>A\rightarrow C</math> | |||
|- | |||
| 11 | |||
| [A: 0, B: 3, C: 1, D: <math>\infty</math>, E: <math>\infty</math>] | |||
| | |||
| | |||
| | |||
| | |||
|- | |||
| 12 | |||
| | |||
| [A: null, B: A, C: A, D: null, E: null] | |||
| | |||
| | |||
| | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>B\rightarrow C</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>B\rightarrow D</math> | |||
|- | |||
| 11 | |||
| [A: 0, B: 3, C: 1, D: -2, E: <math>\infty</math>] | |||
| | |||
| | |||
| | |||
| | |||
|- | |||
| 12 | |||
| | |||
| [A: null, B: A, C: A, D: B, E: null] | |||
| | |||
| | |||
| | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>B\rightarrow E</math> | |||
|- | |||
| 11 | |||
| [A: 0, B: 3, C: 1, D: -2, E: 4] | |||
| | |||
| | |||
| | |||
| | |||
|- | |||
| 12 | |||
| | |||
| [A: null, B: A, C: A, D: B, E: B] | |||
| | |||
| | |||
| | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>C\rightarrow D</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>C\rightarrow E</math> | |||
|- | |||
| 8 | |||
| | |||
| | |||
| 1 | |||
| | |||
| | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>A\rightarrow B</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>A\rightarrow C</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>B\rightarrow C</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>B\rightarrow D</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>B\rightarrow E</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>C\rightarrow D</math> | |||
|- | |||
| 9 | |||
| | |||
| | |||
| | |||
| | |||
| <math>C\rightarrow E</math> | |||
|} | |||
Am Ende des hier dargestellten Ablaufes terminiert der Algorithmus und gibt <code>distance = [A: 0, B: 3, C: 1, D: -2, E: 4]</code>, <code>previous = [A: [[null]], B: A, C: A, D: B, E: B]</code> als Ergebnis zurück. | |||
--> | |||
{{Lückenhaft}} | |||
== Weblinks == | == Weblinks == | ||
* [https:// | * {{VisuAlgo|en/sssp|Der Bellman-Ford-Algorithmus visualisiert}} | ||
* [https://algorithms.discrete.ma.tum.de/graph-algorithms/spp-bellman-ford/index_de.html Erklärung und interaktives Beispiel der TU München] | |||
{{Navigationsleiste Graphalgorithmen}} | |||
[[Kategorie:Graphen]] | [[Kategorie:Graphen]] | ||
[[Kategorie:Algorithmen]] | [[Kategorie:Algorithmen]] |
Aktuelle Version vom 12. November 2024, 14:43 Uhr
Der Bellman-Ford-Algorithmus ist ein Algorithmus, der kürzeste Wege in einem gerichteten Graphen findet. Anders als der Dijkstra-Algorithmus kann der Bellman-Ford-Algorithmus jedoch auch mit negativen Kantengewichten umgehen.
Das Problem
Betrachten wir den nebenstehenden Beispielgraphen, in dem eine Kante negatives Gewicht hat. Der kürzeste Weg von A nach D führt über B und hat die Länge -2. Der Dijkstra-Algorithmus würde aber den Weg über C präferieren, der die Länge 3 hat. Der Dijkstra-Algorithmus ist nämlich greedy und betrachtet immer nur die nächstbeste Kante mit minimalem Gewicht. Bei Graphen mit ausschließlich positiven Kantengewichten ist das kein Problem, da die Gesamtlänge eines Weges immer nur größer werden kann. Bei Graphen, in denen auch negative Kantengewichte vorkommen, dagegen schon, da es hier auch vorteilhaft sein kann, zunächst größere Kantengewichte in Kauf zu nehmen, wenn diese später durch negative Kantengewichte ausgeglichen werden können.
Der Algorithmus
Gegeben seien:
- ein Graph
G
mitn
Knoten - ein Startknoten
s
, von dem aus alle kürzesten Wege berechnet werden sollen
Zu jedem Knoten im Graph wird nun seine Distanz zum Startknoten s
gespeichert sowie der direkte Vorgänger auf dem Weg zu s
. Durch die Vorgänger kann man sich so den kürzesten Weg zu s
erarbeiten.
Der Algorithmus läuft folgendermaßen ab:
- Zu Beginn des Algorithmus wird für jeden Knoten
k
dieDistanz[k]
auf und derVorgänger[k]
aufnull
gesetzt, außer fürs
, dessen Distanz auf 0 gesetzt wird. - Wiederhole
n-1
Mal:- Prüfe für jede Kante
x—y
:- Ist
Distanz[x]
+ Kantenlängex—y
<Distanz[y]
?- Falls ja, setze
Distanz[y]
:=Distanz[x]
+ Kantex—y
… - … und setze
Vorgänger[y]
:=x
- Falls ja, setze
- Ist
- Prüfe für jede Kante
- Zuletzt wird nochmal durch alle Kanten durchiteriert und für jede Kante
x—y
dieselbe Bedingung geprüft:- Ist
Distanz[x]
+ Kantex—y
<Distanz[y]
?- Falls ja, dann enthält der Graph einen Kreis negativer Länge. In diesem Fall können durch wiederholtes Durchlaufen dieses Kreises beliebig kurze Wege erzeugt werden und es kann keine kürzesten Wege geben.
- Falls nein, sind die kürzesten Wege gefunden und die Distanzen und Vorgänger werden zurückgegeben.
- Ist
Beispiel
In diesem Artikel oder Abschnitt fehlen noch wichtige Informationen.
Hilf dem KGS-Wiki, indem du sie recherchierst und einfügst.