0Pricing
DSA Interview Prep · Lektion

Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren

Füllen Sie die Distanzmatrix für alle Knotenpaare mit dem Floyd-Warshall-Algorithmus mit drei verschachtelten Schleifen und wenden Sie ihn an, um die kleinste Anzahl von Sprüngen zwischen allen Knotenpaaren zu finden.

Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren ist eine kostenlose DSA Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des DSA Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der DSA Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Kürzeste Wege zwischen allen Knotenpaaren

Floyd-Warshall berechnet kürzeste Wege zwischen jedem Knotenpaar in einem gewichteten Graphen – auch in Graphen mit negativen Kantengewichten (aber nicht mit negativen Zyklen). Dijkstra von jeder Quelle auszuführen kostet O(V × (V+E) log V); Floyd-Warshall läuft unabhängig von der Kantendichte in O(V³). Für dichte Graphen mit V ≤ 500 ist Floyd-Warshall oft einfacher und ähnlich schnell.

Die zentrale Idee: Zwischenknoten

Floyd-Warshalls zentrale Erkenntnis: dp[i][j][k] = kürzester Pfad von i nach j, der nur Knoten aus {0, 1, ..., k} als Zwischenknoten verwendet. Entweder verwendet der kürzeste Pfad den Knoten k als Zwischenknoten oder nicht. Falls ja: dp[i][j][k] = dp[i][k][k-1] + dp[k][j][k-1]. Falls nicht: dp[i][j][k] = dp[i][j][k-1]. Da die dritte Dimension nur vorwärts fortschreitet, kann sie eliminiert werden – wir aktualisieren direkt an Ort und Stelle.

Initialisierung der Distanzmatrix

Beginnen Sie mit einer V×V-Matrix: dist[i][i] = 0 (Entfernung eines Knotens zu sich selbst), dist[i][j] = weight für direkte Kanten und dist[i][j] = inf für Nichtkanten. Iterieren Sie dann über alle Zwischenknoten k und aktualisieren Sie die Paare (i, j). Die äußere Schleife über k muss zuerst kommen, damit wir Pfade über eine zunehmend größere Menge zulässiger Zwischenknoten korrekt aufbauen.

def floyd_warshall(V, edges):
    INF = float('inf')
    dist = [[INF]*V for _ in range(V)]
    for i in range(V):
        dist[i][i] = 0
    for u, v, w in edges:
        dist[u][v] = w  # directed graph
    
    for k in range(V):       # intermediate node
        for i in range(V):
            for j in range(V):
                if dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]
    
    return dist

Vollständige Implementierung mit Beispiel

Verfolgen wir Floyd-Warshall an einem Graphen mit 4 Knoten. Nach der Verarbeitung jedes Zwischenknotens wird die Matrix um kürzere Pfade ergänzt, die über den Knoten k führen. Der Algorithmus verarbeitet mehrere Sprünge ganz natürlich, indem er kürzeste Pfade schrittweise aufbaut.

def floyd_warshall(V, edges):
    INF = float('inf')
    dist = [[INF]*V for _ in range(V)]
    for i in range(V):
        dist[i][i] = 0
    for u, v, w in edges:
        dist[u][v] = w
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][k] != INF and dist[k][j] != INF:
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
    return dist

V = 4
edges = [(0,1,3),(0,2,7),(1,2,1),(1,3,5),(2,3,2)]
dist = floyd_warshall(V, edges)
for row in dist:
    print([x if x != float('inf') else 'INF' for x in row])

Negative Zyklen erkennen

Überprüfen Sie nach der Ausführung von Floyd-Warshall die Hauptdiagonale: Wenn ein Wert dist[i][i] < 0 ist, gibt es einen negativen Zyklus, der durch den Knoten i verläuft. Das liegt daran, dass ein negativer Zyklus ermöglicht, i von i aus mit negativen Kosten zu erreichen. Wenn kein negativer Zyklus existiert, bleiben alle Diagonaleinträge 0.

def has_negative_cycle_fw(V, edges):
    dist = floyd_warshall(V, edges)
    for i in range(V):
        if dist[i][i] < 0:
            return True  # negative cycle through node i
    return False

# Negative cycle: 0->1->2->0 with weights 1,-3,1 (sum=-1)
edges_neg = [(0,1,1),(1,2,-3),(2,0,1)]
print(has_negative_cycle_fw(3, edges_neg))  # True

Pfadrekonstruktion

Um den tatsächlichen Pfad von i nach j zu rekonstruieren, verwalten Sie eine next[i][j]-Matrix: Initialisieren Sie sie für direkte Kanten mit next[i][j] = j. Bei einer Aktualisierung über den Zwischenknoten k setzen Sie next[i][j] = next[i][k]. Um den Pfad wiederherzustellen, beginnen Sie bei i und folgen den next-Zeigern, bis j erreicht ist. Dies benötigt O(V²) Speicherplatz und O(V) für jede Pfadrekonstruktion.

def fw_with_path(V, edges):
    INF = float('inf')
    dist = [[INF]*V for _ in range(V)]
    nxt = [[None]*V for _ in range(V)]
    for i in range(V): dist[i][i] = 0
    for u, v, w in edges:
        dist[u][v] = w; nxt[u][v] = v
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]
                    nxt[i][j] = nxt[i][k]
    return dist, nxt

def get_path(nxt, i, j):
    if nxt[i][j] is None: return []
    path = [i]
    while i != j:
        i = nxt[i][j]; path.append(i)
    return path

Transitive Hülle

Eine einfachere Variante: Die transitive Hülle beantwortet für alle Paare die Frage „Ist Knoten j von Knoten i aus erreichbar?“. Ersetzen Sie Distanzen durch boolesche Werte: reach[i][j] = reach[i][j] or (reach[i][k] and reach[k][j]). Dies ist Floyd-Warshall mit booleschem OR statt Addition und Minimum. Initialisieren Sie reach[i][i] = True und setzen Sie reach[i][j] = True für direkte Kanten.

def transitive_closure(V, edges):
    reach = [[False]*V for _ in range(V)]
    for i in range(V):
        reach[i][i] = True
    for u, v, _ in edges:
        reach[u][v] = True
    for k in range(V):
        for i in range(V):
            for j in range(V):
                reach[i][j] = reach[i][j] or (reach[i][k] and reach[k][j])
    return reach

edges = [(0,1,1),(1,2,1)]
R = transitive_closure(3, edges)
print(R[0][2])  # True (0 can reach 2 via 0->1->2)

Komplexität und Einsatzgebiete

Floyd-Warshall: O(V³) Zeit, O(V²) Speicherplatz. Für dichte Graphen (E ≈ V²) mit V ≤ 300 ist dieser Algorithmus schneller als Dijkstra V-mal auszuführen (in diesem Fall ebenfalls O(V³)). Für dünn besetzte Graphen mit V = 1000 und E = 3000 kosten V Dijkstra-Ausführungen O(V×E×log V) ≈ 33M, während Floyd-Warshall O(V³) = 10⁹ kostet – Dijkstra ist schneller. Wissen Sie, wann welcher Algorithmus geeignet ist.

Minimale Anzahl von Hops zwischen allen Knotenpaaren

Setzen Sie alle Kantengewichte auf 1 (oder verwenden Sie eine boolesche Adjazenzmatrix mit Floyd-Warshall, wobei Sie Addition statt Minimum verwenden): dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]). Damit wird die minimale Anzahl von Hops zwischen allen Knotenpaaren berechnet – das Ergebnis einer BFS für alle Knotenpaare, aber in einem einzigen Floyd-Warshall-Durchlauf mit O(V³).

def min_hops_all_pairs(V, adj_list):
    INF = float('inf')
    dist = [[INF]*V for _ in range(V)]
    for i in range(V):
        dist[i][i] = 0
        for j in adj_list[i]:
            dist[i][j] = 1
    for k in range(V):
        for i in range(V):
            for j in range(V):
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
    return dist

adj = [[1,2],[2],[3],[],[]]
print(min_hops_all_pairs(5, adj)[0])  # [0, 1, 1, 2, INF]

Interviewkontext: Wenn Interviewer nach Floyd-Warshall fragen

Floyd-Warshall kommt in Interviews bei Aufgaben vor, die Folgendes betreffen: (1) Distanzen zwischen allen Knoten eines kleinen Graphen, (2) das Ermitteln eines Zyklus mit einem negativen Gesamtgewicht, (3) die Berechnung kürzester Wege in Problemen zur Constraint-Propagation und (4) Aufgaben, die ausdrücklich Lösungen mit O(V³) verlangen, wobei V ≤ 200 gilt. Erwähnen Sie in einem Interview immer die Struktur mit drei Schleifen sowie die Voraussetzung, dass keine negativen Zyklen vorhanden sein dürfen, damit der Algorithmus korrekt ist.

Ungerichtete Graphen mit Floyd-Warshall

Fügen Sie bei ungerichteten Graphen für jede Kante beide Richtungen hinzu: dist[u][v] = dist[v][u] = weight. Der Rest des Algorithmus bleibt identisch. Die resultierende Matrix ist symmetrisch: dist[i][j] == dist[j][i] für alle Knotenpaare. Achten Sie bei der Initialisierung darauf, nicht versehentlich gerichtete Kanten zuzuweisen – ungerichtete Kanten müssen vor Ausführung der drei Schleifen in beiden Richtungen zur Anfangsmatrix hinzugefügt werden.

def fw_undirected(V, edges):
    INF = float('inf')
    dist = [[INF]*V for _ in range(V)]
    for i in range(V): dist[i][i] = 0
    for u, v, w in edges:
        dist[u][v] = w
        dist[v][u] = w  # both directions for undirected
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]
    return dist

Schnelltest

Testen Sie Ihr Verständnis der Konzepte aus dieser Lektion im Bereich Data Structures & Algorithms — Coding Interview Prep.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Floyd-Warshall berechnet die kürzesten Wege zwischen allen Knotenpaaren mit drei verschachtelten Schleifen und der Rekurrenz dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]), negative Zyklen lassen sich erkennen, indem nach Abschluss geprüft wird, ob ein dist[i][i] < 0 ist, und der Algorithmus benötigt O(V³) Zeit und O(V²) Speicherplatz. Als Nächstes sehen wir uns Anwendungen kürzester Wege mit Network Delay Time sowie Techniken zur Pfadrekonstruktion an.

Häufig gestellte Fragen

Ist die Lektion „Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren“ kostenlos?

Ja — der vollständige Text von „Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des DSA Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der DSA Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren“?

Füllen Sie die Distanzmatrix für alle Knotenpaare mit dem Floyd-Warshall-Algorithmus mit drei verschachtelten Schleifen und wenden Sie ihn an, um die kleinste Anzahl von Sprüngen zwischen allen Knote… Du übst DSA Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um DSA Interview Prep zu starten?

Keine Vorkenntnisse erforderlich. DSA Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser DSA Interview Prep-Lektion Code schreiben und ausführen?

Ja. Jede DSA Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Dijkstras Algorithmus mit einer Priority Queue
  2. Bellman-Ford und negative Zyklen
  3. Floyd-Warshall: Kürzeste Wege zwischen allen Knotenpaaren
  4. Network Delay Time und Pfadrekonstruktion
← Zurück zu DSA Interview Prep