Menu
Coddy logo textTech

Topologische Sortierung

Zuletzt aktualisiert

Eine topologische Sortierung eines gerichteten azyklischen Graphen (DAG) ist eine lineare Anordnung seiner Knoten, sodass für jede Kante u → v der Knoten u vor v steht. Sie beantwortet Fragen wie „In welcher Reihenfolge kann ich diese Aufgaben ausführen, sodass jede Voraussetzung zuerst abgeschlossen ist?“ Drücke oben auf Wiedergabe, um zu sehen, wie der Kahn-Algorithmus die Knoten in einer gültigen Reihenfolge herauslöst.

Der Kahn-Algorithmus nimmt wiederholt einen Knoten ohne verbleibende eingehende Kanten (Eingangsgrad 0), hängt ihn an die Reihenfolge an und entfernt seine ausgehenden Kanten - was neue Knoten mit Eingangsgrad 0 freisetzen kann. Er funktioniert nur auf einem DAG: Existiert ein Zyklus, erreichen manche Knoten nie den Eingangsgrad 0 und es gibt keine gültige Reihenfolge. Er läuft in O(V + E) Zeit.

Zeit- und Speicherkomplexität

MaßKomplexitätAnmerkungen
ZeitO(V + E)Jeder Knoten einmal ausgegeben, jede Kante einmal entfernt
SpeicherO(V)Eingangsgrad-Zähler + Bereit-Menge + Reihenfolge
ErfordertEinen DAGZyklen haben keine topologische Sortierung
ErgebnisNicht eindeutigEs können viele gültige Reihenfolgen existieren

Schritt für Schritt (Kahn-Algorithmus)

SchrittWas passiert
1Berechne den Eingangsgrad (Anzahl eingehender Kanten) jedes Knotens.
2Sammle alle Knoten mit Eingangsgrad 0 in einer Bereit-Menge.
3Nimm einen bereiten Knoten und hänge ihn an die Ausgabereihenfolge an.
4Verringere den Eingangsgrad jedes seiner Nachfolger.
5Jeder Nachfolger, der den Eingangsgrad 0 erreicht, tritt der Bereit-Menge bei.
6Wiederhole, bis die Bereit-Menge leer ist.

Durchgerechnetes Beispiel

Sortierung des DAG mit den Kanten A→C, B→C, C→D, C→E, D→F, E→F (Anfangs-Eingangsgrade A:0 B:0 C:2 D:1 E:1 F:2):

SchrittBereit-MengeReihenfolgeAktion
0{A, B}[]A und B starten mit Eingangsgrad 0, also sind beide bereit.
1{B}[A]Gib A aus; seine Kante A→C senkt Cs Eingangsgrad von 2 → 1.
2{C}[A, B]Gib B aus; seine Kante B→C senkt C von 1 → 0, also wird C bereit.
3{D, E}[A, B, C]Gib C aus; die Kanten C→D und C→E senken D und E auf 0, beide werden bereit.
4{E}[A, B, C, D]Gib D aus; seine Kante D→F senkt Fs Eingangsgrad von 2 → 1.
5{F}[A, B, C, D, E]Gib E aus; seine Kante E→F senkt F von 1 → 0, also wird F bereit.
6{}[A, B, C, D, E, F]Gib F aus; die Bereit-Menge ist leer und alle 6 Knoten sind geordnet - fertig.

Wann die topologische Sortierung verwenden

Verwende sie, wennVermeide sie, wenn
Du eine Reihenfolge brauchst, die Abhängigkeiten respektiert (Build-Schritte, Paketinstallationen, Kursvoraussetzungen).Der Graph ungerichtet ist - die topologische Ordnung ist nur für gerichtete Graphen definiert.
Der Graph ein DAG ist und du irgendeine gültige lineare Reihenfolge willst.Der Graph Zyklen enthalten kann und du trotzdem eine totale Ordnung brauchst (es gibt keine).
Du Zyklen günstig erkennen willst - eine fehlgeschlagene topologische Sortierung beweist, dass einer existiert.Du die kürzeste oder optimale Reihenfolge nach einem Gewicht brauchst; die einfache topologische Sortierung ignoriert Gewichte.
Du die Reihenfolge einmal in O(V + E) verarbeitest.Die Kanten sich ständig ändern und du bei jeder Aktualisierung neu sortieren musst, wo eine inkrementelle Struktur besser passt.

Topological Sort-Code

Eine saubere, lauffähige Topological Sort-Implementierung in Python, JavaScript, Java, C++, C. Wähle eine Sprache, kopiere den Code oder öffne ihn vorgeladen im Coddy-Playground.

Topological Sort-Code in Python

Python
1from collections import deque2
3
4def topological_sort(graph):5    # Kahn's algorithm: repeatedly remove nodes with no incoming edges6    in_degree = {node: 0 for node in graph}7    for node in graph:8        for neighbor in graph[node]:9            in_degree[neighbor] += 110    queue = deque(node for node in graph if in_degree[node] == 0)11    order = []12    while queue:13        node = queue.popleft()14        order.append(node)15        for neighbor in graph[node]:16            in_degree[neighbor] -= 117            if in_degree[neighbor] == 0:18                queue.append(neighbor)19    if len(order) != len(graph):20        raise ValueError("Graph has a cycle, no topological order")21    return order22
23
24graph = {25    "shirt": ["tie", "jacket"],26    "tie": ["jacket"],27    "pants": ["shoes", "jacket"],28    "socks": ["shoes"],29    "shoes": [],30    "jacket": [],31}32
33print(" -> ".join(topological_sort(graph)))
Führe diesen Code im Python-Playground aus

FAQ zur topologischen Sortierung

Wofür wird eine topologische Sortierung verwendet?
Sie ordnet Aufgaben so, dass jede Abhängigkeit vor dem steht, was sie benötigt. Reale Anwendungen sind Build-Systeme und Paketmanager (Abhängigkeiten zuerst kompilieren), die Kursplanung mit Voraussetzungen und die Auswertungsreihenfolge von Tabellenkalkulationsformeln.
Wie hoch ist die Zeitkomplexität der topologischen Sortierung?
Sowohl der Kahn-Algorithmus als auch der DFS-basierte Ansatz laufen in O(V + E) Zeit, da jeder Knoten einmal verarbeitet und jede Kante einmal geprüft wird. Sie benötigen O(V) zusätzlichen Speicher.
Warum erfordert die topologische Sortierung einen DAG?
Ein gerichteter Zyklus erzeugt einen Widerspruch: Wenn a vor b und b vor a stehen muss, erfüllt keine lineare Ordnung beides. Daher existiert eine topologische Sortierung genau dann, wenn der Graph ein gerichteter azyklischer Graph ist. Der Kahn-Algorithmus erkennt einen Zyklus, wenn er endet, bevor alle Knoten ausgegeben wurden.
Was ist der Unterschied zwischen dem Kahn-Algorithmus und der DFS-basierten topologischen Sortierung?
Der Kahn-Algorithmus ist iterativ und BFS-ähnlich: Er entfernt wiederholt Knoten mit Eingangsgrad 0, was die Zyklenerkennung und die Ordnung vollständig explizit macht. Der DFS-Ansatz besucht Knoten rekursiv und stellt jeden an den Anfang der Reihenfolge, wenn seine Rekursion endet, wodurch die Umkehrung der Endzeiten entsteht. Beide sind O(V + E); Kahn vermeidet tiefe Rekursion und legt die Bereit-Menge natürlich offen, während DFS oft kürzer zu schreiben ist.
Wann sollte ich eine topologische Sortierung statt einer normalen Sortierung verwenden?
Verwende die topologische Sortierung, wenn die Reihenfolge durch Abhängigkeiten zwischen Elementen statt durch einen vergleichbaren Schlüssel bestimmt wird. Ein Vergleichssortierverfahren wie der O(n log n)-Mergesort ordnet nach Wert; die topologische Sortierung ordnet nach „muss davor kommen“-Kanten und kann im Gegensatz zu einem Vergleichssortierverfahren viele gültige Antworten für dieselbe Eingabe liefern.
Ist das Ergebnis einer topologischen Sortierung eindeutig?
Meist nicht. Immer wenn zwei oder mehr Knoten gleichzeitig bereit sind (Eingangsgrad 0), kannst du sie in beliebiger Reihenfolge ausgeben, sodass die meisten DAGs mehrere gültige topologische Sortierungen zulassen. Die Reihenfolge ist nur dann eindeutig, wenn es in jedem Schritt genau einen bereiten Knoten gibt, was der Fall ist, wenn der DAG eine einzige Kette bildet (einen Hamilton-Pfad).
Coddy programming languages illustration

Meistere Algorithmen mit Coddy

LOS GEHT'S