Lernmodul 7 Algorithmus von Floyd
Quelle der Karte: http://www.map24.de
Algorithmus von Floyd Übersicht
l Formulierung/Lösung des Problems
l Vorgehen in Kürze
l Beispiel zum Ablauf des Floyd
l Beschreibung des Algorithmus
l Implementierungen
¡ mit Adjazenzmatrix (Pseudo-Code)
¡ unter Mitführung der kürzesten Wege
¡ Ausgabe der kürzesten Wege
Floyd Formulierung/Lösung des Problems
l Gegeben:Gerichteter Graph G, dessen Kanten mit Zahlen (Kosten, z.B. km oder min.) beschriftet sind
l Bisher: Berechnung der kürzesten Wege von einem Startknoten zu allen anderen Knoten im Graphen (1:n)
¡ Algorithmus von Dijkstra
¡ "single source shortest path"
l Jetzt: Berechnung der kürzesten Wege zwischen allen Paaren von Knoten
¡ "all pairs shortest path"
¡ Lösung:
n Iterative Anwendung des Algorithmus von Dijkstra auf jeden Knoten des Graphen
n Besser: Algorithmus von Floyd
Floyd Vorgehen in Kürze
l Betrachte alle Paare von Vorgängern und Nachfolgern des aktuellen
Knotens
l füge neue direkte Kante ein, wenn zwischen diesen Vorgänger und Nachfolger noch keine Kante existiert
l reduziere die Kosten einer Kante, wenn eine kürzere Verbindung gefunden wird
l Wiederhole diese Betrachung für jeden Knoten
1x
Floyd Beispiel zum Ablauf
l Betrachte alle Vorgänger und Nachfolger des aktuellen Knotens
l füge ggf. neue direkte Kante ein
l reduziere ggf. die Kosten einer Kante
l Wiederholung für jeden Knoten
29x
Floyd Beschreibung des Algorithmus I
Idee: In einem Graphen G mit n Knoten (durchnumeriert von 1 bis n) wird eine Folge von Graphen G0 bis Gn berechnet. Graph Gi entsteht durch Modifikation des Graphen Gi-1.
Für Gi gilt:
1. Gi hat die gleiche Knotenmenge wie G.
2. Es existiert in Gi eine Kante (v,w) mit den Kosten dist(v,w) <=> es existiert in G ein Pfad von v nach w, in dem als Zwischenknoten nur Knoten aus der Menge {1, ..., i} verwendet werden. Der kürzeste derartige Pfad hat die Kosten dist(v,w).
Floyd Beschreibung des Algorithmus II
Es sei G0 = G. G0 erfüllt die Definition des Gi, Gi wird dann aus Gi-1wie folgt berechnet:
v1, ..., vr seien die Vorgänger von Knoten i im Graphen Gi-1, w1, ..., ws die
Nachfolger. Es werden alle Paare (vj, wk) mit j = 1, ..., r und k = 1, ..., s betrachtet:
1. Falls noch keine Kante von vj nach wk existiert, erzeuge eine Kante (vj,wk). Die Kosten dieser Kante sind die Kosten des Pfades von vj nach wküber i.
2. Falls schon eine Kante (vj, wk) existiert, werden die Kosten dieser Kante durch die Kosten des Pfades (vj, wk) ersetzt, falls dist(vj,i)+dist(i,wk) < dist(vj,wk).
Mit vollständiger Induktion läßt sich zeigen, dass Gi die Definition erfüllt. In Gi-1 waren alle kürzesten Pfade bekannt und durch Kanten repräsentiert, als
Zwischenknoten wurden Knoten aus {1,...,i-1} benutzt. In Gi sind alle Pfade über die Knoten {1,..., i} bekannt, in Gn dann die Kosten aller kürzesten Wege in G.
Floyd Implementierung
Es gibt zwei Möglichkeiten der Implementierung 1. mit der Adjazenzmatrix:
¡ C sei die Kostenmatrix für G
¡ Es gilt Cii = 0 und Cij = 8, falls es in G keine Kante von Knoten i nach j gibt
¡ >>Pseudo-Code 2. mit Adjazenzlisten:
¡ Es gibt Adjazenzlisten für die Vorgänger- und Nachfolgerknoten
¡ In jedem Schritt werden alle Elemente der Vorgängerliste des Knotens i mit allen allen Elementen der Nachfolgerliste kombiniert
¡ Für r Vorgänger und s Nachfolger ergibt sich ein Aufwand von O(r s)
¡ Meist wird die Implementierung über die Adjazenzmatrix vorgezogen
Floyd Implementierung mit Adjazenzmatrix
private floyd (float A [n,n], float C [n,n]) {
int i, j, k;
for ( j = 1; j <= n; j++ ) {
for ( k = 1; k <=n; k++ ) //A: Wege A[j,k] = C[j,k]; //C: Kanten }
for( i = 1; i <= n; i++ ) {
for( j = 1; j <= n; j++ ) {
for( k = 1; k <= n; k++ ) {
if ( A[j,i] + A[i,k] < A[j,k] ){
A[j,k] = A[j,i] + A[i,k]; } } } } }
Floyd Mitführung der kürzesten Wege
private floyd (float A [n,n], float C [n,n], int W[n,n]) {
int i, j, k;
for ( j = 1; j <= n; j++ ) {
for ( k = 1; k <=n; k++ ) //A: Wege
{ A[j,k] = C[j,k]; W[j,k] = 8; } //C: Kanten, ggf. ? }
for( i = 1; i <= n; i++ ) {
for( j = 1; j <= n; j++ ) {
for( k = 1; k <= n; k++ ) {
if ( A[j,i] + A[i,k] < A[j,k] ){
A[j,k] = A[j,i] + A[i,k];
W[j,k] = i ; } } } } }
Floyd Ausgabe der kürzesten Wege
l Anhand der Matrizen A und W läßt sich der kürzeste Pfad für zwei beliebige Knoten in O(m) ausgeben (m = Länge des Pfades)
l Beachten Sie:
¡ Die Ausgabeprozedur setzt voraus, dass ein Weg zwischen 2 Knoten x und y existiert
l Übung:
¡ Wie sehen Sie der Matrix A an, ob ein Weg zwischen 2 Knoten existiert
¡ Allgemeiner: Wie sehen Sie anhand der Matrix A, ob der Graph zusammenhängend ist
¡ Der Graph ist zusammenhängend, wenn zwischen jedem Paar (a,b) von Knoten ein Weg existiert
¡ Beachten Sie, dass wir von gerichteten Graphen sprechen, also (a,b) ? (b,a)
Floyd Ausgabe der kürzesten Weges - Pseudo-Code
public weg(int[][] W,int X,int Y) {
weg_rekursiv(W,X,Y);
gib Y aus;
}
private weg_rekursiv(int[][] W,int X,int Y) {
if ( W[X,Y] = 8 ) then gib X aus;
else {
Z = W[X,Y];
weg_rekursiv(W,X,Z);
weg_rekursiv(W,Z,Y);
} }
Algorithmus von Floyd Literatur
Güting, Ralf, Stefan Dieker: Datenstrukturen und Algorithmen. 2. Auflage - B.G.
Teubner, Stuttgart, Leipzig, Wiesbaden, 2003