Tri topologique : Python, C++ Exemple d'algorithme
Quโest-ce que lโalgorithme de tri topologique ?
Le tri topologique est รฉgalement connu sous le nom d'algorithme de Kahn et est un algorithme de tri populaire. En utilisant un graphe orientรฉ comme entrรฉe, Topological Sort trie les nลuds afin que chacun apparaisse avant celui vers lequel il pointe.
Cet algorithme est appliquรฉ sur un DAG (Directed Acyclic Graph) afin que chaque nลud apparaisse dans le tableau ordonnรฉ avant que tous les autres nลuds ne pointent vers lui. Cet algorithme suit certaines rรจgles ร plusieurs reprises jusqu'ร ce que le tri soit terminรฉ.
Pour simplifier, regardez l'exemple suivant :

Ici, nous pouvons voir que ยซ A ยป nโa pas de diplรดme. Cela signifie le bord qui pointe vers un nลud. ยซ B ยป et ยซ C ยป ont un prรฉ-requis de ยซ A ยป, puis ยซ E ยป a un prรฉ-requis de nลuds ยซ D ยป et ยซ F ยป. Certains nลuds dรฉpendent dโautres nลuds.
Voici une autre reprรฉsentation du graphique ci-dessus :
Ainsi, lorsque nous passons le DAG (Directed Acyclic Graph) au tri topologique, cela nous donnera un tableau avec un ordre linรฉaire, oรน le premier รฉlรฉment n'a aucune dรฉpendance.
Cet exemple montre un graphique avec un cycle :
Voici les รฉtapes pour ce faire :
รtape 1) Trouvez le nลud avec zรฉro arรชte entrante, un nลud avec zรฉro degrรฉ.
รtape 2) Stockez qui remet ร zรฉro le nลud en degrรฉ dans une file d'attente ou une pile et supprime le nลud du graphique.
รtape 3) Supprimez ensuite le bord sortant de ce nลud.
Cela diminuera le nombre de degrรฉs pour le nลud suivant.
L'ordre topologique nรฉcessite que la structure des donnรฉes du graphique n'ait aucun cycle.
Un graphique sera considรฉrรฉ comme un DAG sโil respecte ces exigences :
- Un ou plusieurs nลuds avec une valeur indegree de zรฉro.
- Le graphique ne contient aucun cycle
Tant qu'il y a des nลuds dans le graphique et que le graphique est toujours DAG, nous exรฉcuterons les trois รฉtapes ci-dessus. Sinon, l'algorithme tombera dans la dรฉpendance cyclique et l'algorithme de Kahn ne pourra pas trouver un nลud avec un degrรฉ nul.
Comment fonctionne le tri topologique
Ici, nous utiliserons ยซ l'algorithme de Kahn ยป pour le tri topologique. Disons que nous avons le graphique suivant :
Voici les รฉtapes de l'algorithme de Kahn :
รtape 1) Calculez le degrรฉ entrant ou le bord entrant de tous les nลuds du graphique.
ร noter:
- Indegree signifie les bords dirigรฉs pointant vers le nลud.
- Outdegree dรฉsigne les arรชtes dirigรฉes provenant dโun nลud.
Voici le degrรฉ d'entrรฉe et de sortie du graphique ci-dessus :
รtape 2) Trouvez le nลud avec zรฉro degrรฉ ou zรฉro arรชte entrante.
Le nลud avec un degrรฉ nul signifie qu'aucun bord ne se dirige vers ce nลud. Le nลud ยซ A ยป a zรฉro degrรฉ, ce qui signifie qu'il n'y a aucun bord pointant vers le nลud ยซ A ยป.
Nous allons donc effectuer les actions suivantes :
- Supprimez ce nลud et ses bords extรฉrieurs (bords sortants)
- Placez le nลud dans la file d'attente pour la commande.
- Mettez ร jour le nombre de degrรฉs du nลud voisin de ยซ A ยป.
รtape 3) Nous devons trouver un nลud avec une valeur indegree de zรฉro. Dans cet exemple, ยซ B ยป et ยซ C ยป ont un degrรฉ nul.
Ici, nous pouvons prendre lโun ou lโautre de ces deux. Prenons ยซ B ยป et supprimons-le du graphique.
Mettez ensuite ร jour les valeurs indegree des autres nลuds.
Aprรจs avoir effectuรฉ ces opรฉrations, notre graphique et notre file d'attente ressembleront ร ce qui suit :
รtape 4) Le nลud ยซ C ยป n'a pas de bord entrant. Nous allons donc supprimer le nลud ยซ C ยป du graphique et le placer dans la file d'attente.
Nous pouvons รฉgalement supprimer le bord sortant de ยซ C ยป.
Maintenant, notre graphique ressemblera ร ceci :
รtape 5) On peut voir que les nลuds ยซ D ยป et ยซ F ยป ont le degrรฉ zรฉro. Nous allons prendre un nลud et le mettre dans la file d'attente.
Supprimons d'abord ยซ D ยป. Ensuite, le nombre de degrรฉs pour le nลud ยซ E ยป sera de 1. Dรฉsormais, il n'y aura plus de nลud de D ร E.
Nous devons faire la mรชme chose pour le nลud ยซ F ยป, notre rรฉsultat sera le suivant :
รtape 6) Le degrรฉ entrant (bords entrants) et le degrรฉ sortant (bords sortants) du nลud ยซ E ยป sont devenus nuls. Nous avons donc rempli tous les prรฉ-requis pour le nลud ยซ E ยป.
Ici, nous mettons ยซ E ยป ร la fin de la file dโattente. Il ne nous reste donc plus aucun nลud, donc l'algorithme se termine ici.
Pseudo-code pour le tri topologique
Voici le pseudo-code pour le tri topologique en utilisant l'algorithme de Kahn.
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
Le tri topologique peut รฉgalement รชtre implรฉmentรฉ ร l'aide du DFS (Premiรจre recherche en profondeur) mรฉthode. Cependant, cette approche est la mรฉthode rรฉcursive. L'algorithme de Kahn est plus efficace que l'approche DFS.
C++ Implรฉmentation du tri topologique
#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();
}
Sortie
0 1 2 3 5 4
Python Implรฉmentation du tri topologique
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()
Sortie
[0, 1, 2, 3, 5, 4]
Graphiques cycliques de l'algorithme de tri topologique
Un graphe contenant un cycle ne peut pas รชtre ordonnรฉ topologiquement. Comme le graphique cyclique a la dรฉpendance de maniรจre cyclique.
Par exemple, vรฉrifiez ce graphique :
Ce graphique n'est pas DAG (Directed Acyclic Graph) car A, B et C crรฉent un cycle. Si vous remarquez, il nโy a aucun nลud avec une valeur en degrรฉ nulle.
Selon l'algorithme de Kahn, si l'on analyse le graphique ci-dessus :
- Trouvez un nลud avec zรฉro degrรฉ (pas de bords entrants).
- Supprimez ce nลud du graphique et placez-le dans la file d'attente.
Cependant, dans le graphique ci-dessus, il nโy a aucun nลud avec zรฉro en degrรฉs. Chaque nลud a une valeur en degrรฉ supรฉrieure ร 0. - Renvoie une file d'attente vide, car elle n'a trouvรฉ aucun nลud avec zรฉro en degrรฉs.
Nous pouvons dรฉtecter les cycles en utilisant l'ordre topologique avec les รฉtapes suivantes :
รtape 1) Effectuez un tri topologique.
รtape 2) Calculez le nombre total dโรฉlรฉments dans la liste triรฉe topologiquement.
รtape 3) Si le nombre dโรฉlรฉments est รฉgal au nombre total de sommets, alors il nโy a pas de cycle.
รtape 4) S'il n'est pas รฉgal au nombre de sommets, alors il y a au moins un cycle dans la structure de donnรฉes du graphique donnรฉe.
Analyse de complexitรฉ du tri topologique
Il existe deux types de complexitรฉ dans les algorithmes. Ils sont
- Complexitรฉ temporelle
- Complexitรฉ spatiale
Ces complexitรฉs sont reprรฉsentรฉes par une fonction qui fournit une complexitรฉ gรฉnรฉrale.
Complexitรฉ temporelle: Toute complexitรฉ temporelle est la mรชme pour le tri topologique. Il existe des scรฉnarios pires, moyens et meilleurs en matiรจre de complexitรฉ temporelle.
La complexitรฉ temporelle pour le tri topologique est O(E + V), ici, E signifie le nombre d'arรชtes dans le graphe et V signifie le nombre de sommets dans le graphe.
Brisons cette complexitรฉ :
รtape 1) Au dรฉbut, nous calculerons tous les degrรฉs. Pour ce faire, nous devons parcourir toutes les arรชtes et, dans un premier temps, nous attribuerons ร zรฉro tous les degrรฉs du sommet V. Ainsi, les รฉtapes progressives que nous accomplirons seront O(V+T).
รtape 2) Nous trouverons le nลud avec une valeur de degrรฉ nulle. Nous devons rechercher ร partir du numรฉro V du sommet. Ainsi, les รฉtapes complรฉtรฉes seront O (V).
รtape 3) Pour chaque nลud avec zรฉro degrรฉ, nous supprimerons ce nลud et dรฉcrรฉmenterons le degrรฉ. Effectuer cette opรฉration pour tous les nลuds prendra O(E).
รtape 4) Enfin, nous vรฉrifierons s'il y a un cycle ou non. Nous vรฉrifierons si le nombre total d'รฉlรฉments dans le tableau triรฉ est รฉgal au nombre total de nลuds. รa prendra O (1).
Il s'agissait donc de la complexitรฉ temporelle individuelle pour chaque รฉtape du tri topologique ou de l'ordre topologique. Nous pouvons dire que la complexitรฉ temporelle du calcul ci-dessus sera O( V + E ) ; ici, O signifie la fonction de complexitรฉ.
Complexitรฉ de l'espace: Nous avions besoin d'espaces O(V) pour exรฉcuter l'algorithme de tri topologique.
Voici les รฉtapes pour lesquelles nous avions besoin d'espace pour le programme :
- Nous avons dรป calculer tous les degrรฉs de nลuds prรฉsents dans le graphique. Comme le graphique a un total de nลuds V, nous devons crรฉer un tableau de taille V. Ainsi, l'espace requis รฉtait O (V).
- Une structure de donnรฉes Queue a รฉtรฉ utilisรฉe pour stocker le nลud avec un degrรฉ nul. Nous avons supprimรฉ les nลuds avec un degrรฉ nul du graphique d'origine et les avons placรฉs dans la file d'attente. Pour cela, l'espace requis รฉtait O (V).
- Le tableau est nommรฉ ยซ ordre ยป. Cela a stockรฉ les nลuds dans l'ordre topologique. Cela nรฉcessitait รฉgalement O (V) les espaces.
Il s'agissait de la complexitรฉ de l'espace individuel. Nous devons donc maximiser ces espaces au moment de lโexรฉcution.
La complexitรฉ spatiale signifie O(V), oรน V dรฉsigne le numรฉro du sommet dans le graphique.
Application du tri topologique
Le tri topologique est trรจs utilisรฉ. En voici quelques uns:
- Il est utilisรฉ lorsque Systรจme exploitation doit effectuer lโallocation des ressources.
- Trouver un cycle dans le graphique. Nous pouvons valider si le graphe est DAG ou non avec un tri topologique.
- Ordre des phrases dans les applications de saisie semi-automatique.
- Il est utilisรฉ pour dรฉtecter impasses.
- Diffรฉrents types de planification ou de planification de cours utilisent le tri topologique.
- Rรฉsoudre les dรฉpendances. Par exemple, si vous essayez d'installer un package, ce package peut รฉgalement nรฉcessiter d'autres packages. L'ordre topologique dรฉcouvre tous les packages nรฉcessaires pour installer le package actuel.
- Linux utilise le tri topologique dans ยซ apt ยป pour vรฉrifier la dรฉpendance des packages.









