Topologischer Sortieralgorithmus: Python, C++ Beispiel
โก Intelligente Zusammenfassung
Die topologische Sortierung ordnet die Knoten eines gerichteten azyklischen Graphen so, dass jeder Knoten vor denjenigen erscheint, auf die er zeigt. Dabei wird Kahns Algorithmus verwendet, um wiederholt Knoten mit Eingangsgrad Null auszuwรคhlen.

Was ist ein topologischer Sortieralgorithmus?
Die topologische Sortierung wird auch als Kahn-Algorithmus bezeichnet und ist ein beliebter Sortieralgorithmus. Unter Verwendung eines gerichteten Graphen als Eingabe sortiert Topological Sort die Knoten so, dass jeder vor dem Knoten erscheint, auf den er zeigt.
Dieser Algorithmus wird auf einen gerichteten azyklischen Graphen (DAG) angewendet, sodass jeder Knoten in der sortierten Liste vor allen anderen Knoten erscheint, auf die er verweist. Der Algorithmus befolgt bestimmte Regeln wiederholt, bis die Sortierung abgeschlossen ist.
Betrachten Sie zur Vereinfachung das folgende Beispiel:
Gerichteter Graph
Hier sehen wir, dass Knoten โAโ keinen Eingangsgrad hat. Der Eingangsgrad bezeichnet die Kante, die auf einen Knoten verweist. Knoten โBโ und โCโ benรถtigen Knoten โAโ, und Knoten โEโ benรถtigt Knoten โDโ und โFโ. Einige Knoten sind also voneinander abhรคngig.
Hier ist eine weitere Darstellung des obigen Graphen:
Abhรคngigkeit jedes Knotens (lineare Reihenfolge)
Wenn wir also den DAG (Directed Asymmetric Graph) an die topologische Sortierung รผbergeben, erhalten wir ein Array mit linearer Reihenfolge, bei dem das erste Element keine Abhรคngigkeit hat.
Hier sind die Schritte dazu:
Schritt 1) Suchen Sie den Knoten mit null eingehenden Kanten, einen Knoten mit null Grad.
Schritt 2) Speichere den Knoten mit dem Eingangsgrad Null in einer Warteschlange oder einem Stapel und entferne den Knoten aus dem Graphen.
Schritt 3) Lรถschen Sie anschlieรend die ausgehende Kante dieses Knotens. Dadurch wird der Eingangsgrad des nรคchsten Knotens verringert.
Die topologische Ordnung erfordert, dass die Graphdatenstruktur keine Zyklen enthรคlt. Ein Graph gilt als gerichteter azyklischer Graph (DAG), wenn er folgende Anforderungen erfรผllt:
- Ein oder mehrere Knoten mit einem Gradwert von Null.
- Der Graph enthรคlt keinen Zyklus.
Solange der Graph Knoten enthรคlt und ein gerichteter azyklischer Graph (DAG) ist, werden die oben genannten drei Schritte ausgefรผhrt. Andernfalls gerรคt der Algorithmus in eine zyklische Abhรคngigkeit, und der Kahn-Algorithmus findet keinen Knoten mit Eingangsgrad Null.
So funktioniert die topologische Sortierung
Hier verwenden wir den โKahn-Algorithmusโ fรผr die topologische Sortierung. Angenommen, wir haben den folgenden Graphen:
Hier sind die Schritte des Kahn-Algorithmus:
Schritt 1) Berechnen Sie den Eingangsgrad oder die Eingangskante aller Knoten im Diagramm.
Hinweis:
- Ingrad bezeichnet die gerichteten Kanten, die auf den Knoten zeigen.
- Unter Grad versteht man die gerichteten Kanten, die von einem Knoten ausgehen.
Hier sind der Eingangsgrad und der Ausgangsgrad des obigen Graphen:
Schritt 2) Finde den Knoten mit dem Eingangsgrad Null bzw. mit null eingehenden Kanten. Ein Knoten mit dem Eingangsgrad Null hat keine Kanten, die zu diesem Knoten fรผhren. Knoten โAโ hat den Eingangsgrad Null, das heiรt, es gibt keine Kante, die auf Knoten โAโ zeigt. Daher fรผhren wir die folgenden Aktionen durch:
- Entferne diesen Knoten und seine ausgehenden Kanten.
- Platzieren Sie den Knoten zur Bestellung in der Warteschlange.
- Aktualisiere den Eingangsgrad des Nachbarknotens von โAโ.
Schritt 3) Wir mรผssen einen Knoten mit Eingangsgrad null finden. In diesem Beispiel haben โBโ und โCโ einen Eingangsgrad von null. Wir kรถnnen einen der beiden auswรคhlen. Nehmen wir โBโ und entfernen ihn aus dem Graphen. Anschlieรend aktualisieren wir die Eingangsgrade der รผbrigen Knoten. Nach diesen Operationen sehen unser Graph und unsere Warteschlange wie folgt aus:
Schritt 4) Knoten โCโ hat keine eingehende Kante. Daher entfernen wir Knoten โCโ aus dem Graphen und fรผgen ihn der Warteschlange hinzu. Wir kรถnnen auch die von โCโ ausgehende Kante lรถschen. Unser Graph sieht nun folgendermaรen aus:
Schritt 5) Wir sehen, dass die Knoten โDโ und โFโ einen Eingangsgrad von null haben. Wir nehmen einen Knoten und fรผgen ihn der Warteschlange hinzu. Nehmen wir zuerst โDโ heraus. Dann betrรคgt der Eingangsgrad fรผr Knoten โEโ 1. Nun gibt es keine Verbindung mehr zwischen D und E. Dasselbe machen wir fรผr Knoten โFโ, und unser Ergebnis sieht dann wie folgt aus:
Schritt 6) Der Eingangsgrad (eingehende Kanten) und Ausgangsgrad (ausgehende Kanten) des Knotens โEโ sind null. Damit sind alle Voraussetzungen fรผr Knoten โEโ erfรผllt. Wir fรผgen โEโ nun am Ende der Warteschlange ein. Es sind keine Knoten mehr รผbrig, und der Algorithmus endet hier.
Spitzname Code fรผr topologische Sortierung
Hier ist der Pseudocode fรผr die topologische Sortierung unter Verwendung des Kahn-Algorithmus.
function TopologicalSort( Graph G ): for each node in G: calculate the indegree start = Node with 0 indegree G.remove(start) topological_list = [start] while node with 0 indegree present: topological_list.append(node) G.remove(node) // Update indegree of present nodes return topological_list
Die topologische Sortierung kann auch mit dem DFS implementiert werden (Tiefe Erste Suche) Methode. Dieser Ansatz ist jedoch die rekursive Methode. Kahns Algorithmus ist effizienter als der DFS-Ansatz.
C++ Implementierung der topologischen Sortierung
#include<bits/stdc++.h> using namespace std; class graph{ int vertices; list<int> *adjecentList; public: graph(int vertices){ this->vertices = vertices; adjecentList = new list<int>[vertices]; } void createEdge(int u, int v){ adjecentList[u].push_back(v); } void TopologicalSort(){ // filling the vector with zero initially vector<int> indegree_count(vertices,0); for(int i=0;i<vertices;i++){ list<int>::iterator itr; for(itr=adjecentList[i].begin(); itr!=adjecentList[i].end();itr++){ indegree_count[*itr]++; } } queue<int> Q; for(int i=0; i<vertices;i++){ if(indegree_count[i]==0){ Q.push(i); } } int visited_node = 0; vector<int> order; while(!Q.empty()){ int u = Q.front(); Q.pop(); order.push_back(u); list<int>::iterator itr; for(itr=adjecentList[u].begin(); itr!=adjecentList[u].end();itr++){ if(--indegree_count[*itr]==0){ Q.push(*itr); } } visited_node++; } if(visited_node!=vertices){ cout<<"There's a cycle present in the Graph.\nGiven graph is not DAG"<<endl; return; } for(int i=0; i<order.size();i++){ cout<<order[i]<<"\t"; } } }; int main(){ graph G(6); G.createEdge(0,1); G.createEdge(0,2); G.createEdge(1,3); G.createEdge(1,5); G.createEdge(2,3); G.createEdge(2,5); G.createEdge(3,4); G.createEdge(5,4); G.TopologicalSort(); }
Ausgang
0 1 2 3 5 4
Python Implementierung der topologischen Sortierung
from collections import defaultdict class graph: def __init__(self, vertices): self.adjacencyList = defaultdict(list) self.Vertices = vertices # No. of vertices # function to add an edge to adjacencyList def createEdge(self, u, v): self.adjacencyList[u].append(v) # The function to do Topological Sort. def topologicalSort(self): total_indegree = [0]*(self.Vertices) for i in self.adjacencyList: for j in self.adjacencyList[i]: total_indegree[j] += 1 queue = [] for i in range(self.Vertices): if total_indegree[i] == 0: queue.append(i) visited_node = 0 order = [] while queue: u = queue.pop(0) order.append(u) for i in self.adjacencyList[u]: total_indegree[i] -= 1 if total_indegree[i] == 0: queue.append(i) visited_node += 1 if visited_node != self.Vertices: print("There's a cycle present in the Graph.\nGiven graph is not DAG") else: print(order) G = graph(6) G.createEdge(0,1) G.createEdge(0,2) G.createEdge(1,3) G.createEdge(1,5) G.createEdge(2,3) G.createEdge(2,5) G.createEdge(3,4) G.createEdge(5,4) G.topologicalSort()
Ausgang
[0, 1, 2, 3, 5, 4]
Zyklische Graphen des topologischen Sortieralgorithmus
Ein Graph, der einen Zyklus enthรคlt, kann nicht topologisch geordnet werden, da die Abhรคngigkeiten im zyklischen Graphen zyklisch sind. Betrachten Sie beispielsweise diesen Graphen:
Dieser Graph ist kein DAG (gerichteter azyklischer Graph), da A, B und C einen Zyklus bilden. Es gibt keinen Knoten mit Eingangsgrad null. Analysiert man den obigen Graphen gemรคร Kahns Algorithmus, ergibt sich Folgendes:
- Suchen Sie einen Knoten mit null Grad (keine eingehenden Kanten).
- Entferne diesen Knoten aus dem Graphen und fรผge ihn der Warteschlange hinzu. Im obigen Graphen gibt es jedoch keinen Knoten mit Eingangsgrad Null. Jeder Knoten hat einen Eingangsgrad grรถรer als 0.
- Es wird eine leere Warteschlange zurรผckgegeben, da kein Knoten mit Eingangsgrad Null gefunden werden konnte.
Wir kรถnnen Zyklen mithilfe der topologischen Ordnung mit den folgenden Schritten erkennen:
Schritt 1) Fรผhren Sie eine topologische Sortierung durch.
Schritt 2) Berechnen Sie die Gesamtzahl der Elemente in der topologisch sortierten Liste.
Schritt 3) Wenn die Anzahl der Elemente der Gesamtzahl der Knoten entspricht, dann gibt es keinen Zyklus.
Schritt 4) Wenn sie nicht gleich der Anzahl der Knoten ist, dann gibt es mindestens einen Zyklus in der gegebenen Graphdatenstruktur.
Komplexitรคtsanalyse der topologischen Sortierung
Es gibt zwei Arten von Komplexitรคt bei Algorithmen. Diese sind:
- Zeitliche Komplexitรคt
- Raumkomplexitรคt
Diese Komplexitรคten werden mit einer Funktion dargestellt, die eine allgemeine Komplexitรคt bereitstellt.
Zeitliche Komplexitรคt: Die Zeitkomplexitรคt des topologischen Sortierens ist immer gleich. Es gibt einen Worst-Case, einen Average und einen Best-Case. Die Zeitkomplexitรคt des topologischen Sortierens betrรคgt O(E + V), wobei E die Anzahl der Kanten und V die Anzahl der Knoten im Graphen bezeichnet.
Lassen Sie uns diese Komplexitรคt รผberwinden:
Schritt 1) Zu Beginn berechnen wir alle Ingrade. Dazu mรผssen wir alle Kanten durchgehen und zunรคchst allen V-Scheitelpunkten den Wert Null zuweisen. Die inkrementellen Schritte, die wir durchfรผhren, werden also sein O(V+E).
Schritt 2) Wir werden den Knoten mit dem Gradwert Null finden. Wir mรผssen anhand der V-Nummer des Scheitelpunkts suchen. Damit sind die Schritte abgeschlossen O (V).
Schritt 3) Fรผr jeden Knoten mit null Eingangsgraden entfernen wir diesen Knoten und verringern den Eingangsgrad. Die Durchfรผhrung dieser Operation fรผr alle Knoten dauert O(E).
Schritt 4) Abschlieรend prรผfen wir, ob es einen Zyklus gibt oder nicht. Wir prรผfen, ob die Gesamtzahl der Elemente im sortierten Array gleich der Gesamtzahl der Knoten ist. Es wird dauern O (1).
Dies waren also die einzelnen Zeitkomplexitรคten fรผr jeden Schritt der topologischen Sortierung bzw. topologischen Ordnung. Die Zeitkomplexitรคt ergibt sich aus der obigen Berechnung zu O(V + E), wobei O die Komplexitรคtsfunktion bezeichnet.
Raumkomplexitรคt: Fรผr die Ausfรผhrung des topologischen Sortieralgorithmus benรถtigten wir O(V) Speicherplatz. Hier sind die Schritte, fรผr die wir Speicherplatz im Programm benรถtigten:
- Wir mussten alle Ingrade der im Diagramm vorhandenen Knoten berechnen. Da der Graph insgesamt V Knoten hat, mรผssen wir ein Array der Grรถรe V erstellen. Der benรถtigte Platz war also O (V).
- Eine Queue-Datenstruktur wurde verwendet, um den Knoten mit einem Grad von Null zu speichern. Wir haben die Knoten mit dem Grad Null aus dem ursprรผnglichen Diagramm entfernt und sie in die Warteschlange gestellt. Dafรผr war der erforderliche Platz vorhanden O (V).
- Das Array trรคgt den Namen โorderโ und speichert die Knoten in topologischer Reihenfolge. Das erforderte auch O (V) Rรคume.
Dies waren die individuellen Speicherkomplexitรคten. Wir mรผssen diese Speicherkapazitรคten also zur Laufzeit maximieren. Die Speicherkomplexitรคt wird mit O(V) bezeichnet, wobei V die Nummer des Knotens im Graphen angibt.
Anwendung der topologischen Sortierung
Topologische Sortierung hat vielfรคltige Einsatzmรถglichkeiten. Hier einige Beispiele:
- Es wird verwendet, wenn ein Betriebssystem muss die Ressourcenzuweisung durchfรผhren.
- Einen Zyklus im Graphen finden. Wir kรถnnen mithilfe der topologischen Sortierung รผberprรผfen, ob der Graph ein DAG ist oder nicht.
- Satzreihenfolge in den Apps zur automatischen Vervollstรคndigung.
- Es wird zur Erkennung verwendet. Deadlocks.
- Verschiedene Arten der Stundenplanung oder Kursplanung nutzen die topologische Sortierung.
- Abhรคngigkeiten auflรถsen. Wenn Sie beispielsweise versuchen, ein Paket zu installieren, benรถtigt dieses Paket mรถglicherweise auch andere Pakete. Durch die topologische Reihenfolge werden alle erforderlichen Pakete ermittelt, um das aktuelle Paket zu installieren.
- Linux verwendet die topologische Sortierung in โaptโ, um die Abhรคngigkeit der Pakete zu รผberprรผfen.











