Topologische Sortierung: Python, C++ Algorithmusbeispiel
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 DAG (Directed Asymmetric Graph) angewendet, sodass jeder Knoten im geordneten Array erscheint, bevor alle anderen Knoten auf ihn verweisen. Dieser Algorithmus folgt einigen Regeln wiederholt, bis die Sortierung abgeschlossen ist.
Betrachten Sie zur Vereinfachung das folgende Beispiel:

Hier kรถnnen wir sehen, dass โAโ keinen Grad hat. Damit ist die Kante gemeint, die auf einen Knoten zeigt. โBโ und โCโ haben die Voraussetzung โAโ, dann hat โEโ die Voraussetzung โDโ- und โFโ-Knoten. Einige der Knoten sind von anderen Knoten abhรคngig.
Hier ist eine weitere Darstellung der obigen Grafik:
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.
Dieses Beispiel zeigt ein Diagramm mit einem Zyklus:
Hier sind die Schritte dazu:
Schritt 1) Suchen Sie den Knoten mit null eingehenden Kanten, einen Knoten mit null Grad.
Schritt 2) Speicher, der In-Grad-Knoten in einer Warteschlange oder einem Stapel auf Null setzt und den Knoten aus dem Diagramm entfernt.
Schritt 3) Lรถschen Sie dann die ausgehende Kante von diesem Knoten.
Dadurch wird die In-Grad-Zรคhlung fรผr den nรคchsten Knoten verringert.
Die topologische Reihenfolge erfordert, dass die Diagrammdatenstruktur keinen Zyklus aufweist.
Ein Diagramm gilt als DAG, wenn es die folgenden Anforderungen erfรผllt:
- Ein oder mehrere Knoten mit einem Gradwert von Null.
- Diagramm enthรคlt keinen Zyklus
Solange es Knoten im Graphen gibt und der Graph noch DAG ist, fรผhren wir die obigen drei Schritte aus. Andernfalls fรคllt der Algorithmus in die zyklische Abhรคngigkeit und Kahns Algorithmus kann keinen Knoten mit einem Eingangsgrad von Null finden.
So funktioniert die topologische Sortierung
Hier verwenden wir โKahns Algorithmusโ fรผr die topologische Sortierung. Nehmen wir an, wir haben den folgenden Graphen:
Hier sind die Schritte fรผr Kahns 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 ist der In-Grad und Out-Grad des obigen Diagramms:
Schritt 2) Suchen Sie den Knoten mit null Grad oder eingehenden Kanten.
Der Knoten mit dem Grad Null bedeutet, dass keine Kanten auf diesen Knoten zukommen. Knoten โAโ hat null Grad, was bedeutet, dass es keine Kante gibt, die auf Knoten โAโ zeigt.
Wir werden also die folgenden Aktionen durchfรผhren:
- Entfernen Sie diesen Knoten und seine Auรenkanten (ausgehende Kanten).
- Platzieren Sie den Knoten zur Bestellung in der Warteschlange.
- Aktualisieren Sie die In-Grad-Anzahl des Nachbarknotens von โAโ.
Schritt 3) Wir mรผssen einen Knoten mit einem Gradwert von Null finden. In diesem Beispiel haben โBโ und โCโ einen Grad von Null.
Hier kรถnnen wir eines dieser beiden nehmen. Nehmen wir โBโ und lรถschen Sie es aus dem Diagramm.
Aktualisieren Sie dann die Indegree-Werte anderer Knoten.
Nach der Durchfรผhrung dieser Vorgรคnge sehen unser Diagramm und unsere Warteschlange wie folgt aus:
Schritt 4) Knoten โCโ hat keine eingehende Kante. Wir entfernen also den Knoten โCโ aus dem Diagramm und verschieben ihn in die Warteschlange.
Wir kรถnnen auch die von โCโ ausgehende Kante lรถschen.
Nun sieht unser Diagramm so aus:
Schritt 5) Wir kรถnnen sehen, dass die Knoten โDโ und โFโ den Grad Null haben. Wir nehmen einen Knoten und stellen ihn in die Warteschlange.
Nehmen wir zuerst โDโ heraus. Dann ist die Ingradzahl fรผr Knoten โEโ 1. Jetzt gibt es keinen Knoten von D nach E.
Das Gleiche mรผssen wir fรผr den Knoten โFโ tun. Unser Ergebnis wird dann wie folgt aussehen:
Schritt 6) Der Indegree (eingehende Kanten) und Outdegree (ausgehende Kanten) des Knotens โEโ wurden Null. Wir haben also alle Voraussetzungen fรผr Knoten โEโ erfรผllt.
Hier setzen wir โEโ an das Ende der Warteschlange. Da wir keine Knoten mehr haben, endet der Algorithmus hier.
Pseudocode 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 O 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 der zyklische Graph die Abhรคngigkeit zyklisch hat.
Sehen Sie sich zum Beispiel diese Grafik an:
Dieser Graph ist kein DAG (Directed Asymmetric Graph), da A, B und C einen Zyklus erzeugen. Wie Sie bemerken, gibt es keinen Knoten mit einem In-Grad-Wert von Null.
Wenn wir gemรคร Kahns Algorithmus die obige Grafik analysieren:
- Suchen Sie einen Knoten mit null Grad (keine eingehenden Kanten).
- Entfernen Sie diesen Knoten aus dem Diagramm und verschieben Sie ihn in die Warteschlange.
Im obigen Diagramm gibt es jedoch keinen Knoten mit Null in Grad. Jeder Knoten hat einen In-Grad-Wert grรถรer als 0. - Gibt eine leere Warteschlange zurรผck, da kein Knoten mit Null in Grad 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 Scheitelpunkte entspricht, gibt es keinen Zyklus.
Schritt 4) Wenn sie nicht der Anzahl der Scheitelpunkte entspricht, gibt es mindestens einen Zyklus in der gegebenen Diagrammdatenstruktur.
Komplexitรคtsanalyse der topologischen Sortierung
Es gibt zwei Arten von Komplexitรคt in Algorithmen. Sie 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 ist bei der topologischen Sortierung immer gleich. Es gibt Worst-Case-, Durchschnitts- und Best-Case-Szenarien fรผr die Zeitkomplexitรคt.
Die Zeitkomplexitรคt fรผr die topologische Sortierung betrรคgt O(E + V), wobei E die Anzahl der Kanten im Graphen und V die Anzahl der Eckpunkte im Graphen bezeichnet.
Lassen Sie uns diese Komplexitรคt durchbrechen:
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 oder topologischen Ordnung. Wir kรถnnen sagen, dass die Zeitkomplexitรคt aus der obigen Berechnung O(V + E) betrรคgt; hier steht O fรผr die Komplexitรคtsfunktion.
Raumkomplexitรคt: Wir brauchten O(V) Rรคume, um den topologischen Sortieralgorithmus auszufรผhren.
Hier sind die Schritte, bei denen wir den Platz fรผr das 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 heiรt โorderโ. Dadurch wurden die Knoten in topologischer Reihenfolge gespeichert. Das war auch erforderlich O (V) Rรคume.
Dies war die individuelle Raumkomplexitรคt. Daher mรผssen wir diese Rรคume wรคhrend der Laufzeit maximieren.
Die rรคumliche Komplexitรคt steht fรผr O(V), wobei V die Nummer der Scheitelpunkte im Graphen bezeichnet.
Anwendung der topologischen Sortierung
Die topologische Sortierung bietet vielfรคltige Einsatzmรถglichkeiten. Hier sind einige davon:
- Es wird verwendet, wenn Betriebssystem muss die Ressourcenzuweisung durchfรผhren.
- Einen Zyklus im Diagramm finden. Mit der topologischen Sortierung kรถnnen wir รผberprรผfen, ob der Graph DAG ist oder nicht.
- Satzreihenfolge in den Apps zur automatischen Vervollstรคndigung.
- Es dient der Erkennung Deadlocks.
- Verschiedene Arten der Terminplanung 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.









