Tri topologique par DFS en post-ordre
Exécutez DFS et empilez chaque nœud une fois ses voisins entièrement explorés, puis dépilez la pile pour obtenir un ordre topologique valide.
Tri topologique par DFS en post-ordre est une leçon Coding Interview Prep gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Coding Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Coding Interview Prep comprend 4 leçons au total.
Idée du tri topologique fondé sur DFS
Le deuxième algorithme classique de tri topologique utilise DFS avec un traitement en postordre. Après avoir exploré complètement tous les voisins d’un sommet, ainsi que leurs descendants, empilez le sommet. Une fois tous les sommets traités, utilisez pop sur la pile pour lire l’ordre topologique. Un sommet empilé après toutes ses dépendances signifie qu’il vient en premier dans l’ordre — le postordre inversé constitue donc le tri topologique.
Intuition du postordre
Considérez un graphe de dépendances où le cours A nécessite le cours B. Lorsque DFS visite A, il commence par appeler récursivement B. B n’a aucun prérequis, il est donc terminé en premier et empilé en premier. A est ensuite terminé et empilé. Dépiler la pile donne A avant B dans la sortie — mais on inverse le résultat à la fin, ce qui donne B avant A : prendre B d’abord, puis A. Le postordre empile les dépendances avant les éléments qui en dépendent ; la pile inversée est donc un ordre topologique valide.
DFS à trois couleurs pour détecter les cycles
Utilisez trois états pour les sommets visités : WHITE (0) = non visité, GREY (1) = en cours de traitement, dans la pile d’appels de DFS, BLACK (2) = entièrement traité. Une arête arrière — une arête vers un sommet GREY — indique un cycle. Les arêtes vers des sommets BLACK sont sûres, car ceux-ci ont déjà été entièrement explorés. Ce schéma à trois couleurs détecte correctement tous les cycles dans les graphes orientés.
WHITE, GREY, BLACK = 0, 1, 2
color = [WHITE] * n # n = number of nodes
# During DFS:
# color[node] = GREY (entering node)
# recurse into neighbours
# if neighbour is GREY: cycle found!
# color[node] = BLACK (leaving node, push to stack)Implémentation complète du tri topologique avec DFS
Utilisez un DFS récursif qui colore les sommets, les empile en postordre et renvoie Faux en cas de détection d’un cycle. Après avoir visité tous les sommets, la pile inversée donne l’ordre topologique.
from collections import defaultdict
def dfs_topological_sort(n, edges):
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
WHITE, GREY, BLACK = 0, 1, 2
color = [WHITE] * n
stack = []
def dfs(node):
color[node] = GREY
for nxt in graph[node]:
if color[nxt] == GREY:
return False # cycle
if color[nxt] == WHITE:
if not dfs(nxt):
return False
color[node] = BLACK
stack.append(node)
return True
for i in range(n):
if color[i] == WHITE:
if not dfs(i):
return [] # cycle
return stack[::-1]
print(dfs_topological_sort(4, [(0,1),(0,2),(1,3),(2,3)]))DFS itératif pour éviter le dépassement de pile
La limite de récursivité de Python, fixée par défaut à 1000, pose problème pour les grands graphes. Un DFS itératif utilisant une pile explicite permet de l’éviter. L’astuce consiste à empiler d’abord (node, False) ; lorsqu’il est dépilé avec False, empilez (node, True), ce qui signifie « je reviendrai ici après l’exploration », puis empilez tous les voisins non visités avec Faux. Lorsqu’il est dépilé avec True, colorez-le en BLACK et empilez-le dans la pile de résultats.
from collections import defaultdict
def dfs_topo_iterative(n, edges):
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
WHITE, GREY, BLACK = 0, 1, 2
color = [WHITE] * n
result = []
for start in range(n):
if color[start] != WHITE:
continue
stack = [(start, False)]
while stack:
node, returning = stack.pop()
if returning:
color[node] = BLACK
result.append(node)
elif color[node] == WHITE:
color[node] = GREY
stack.append((node, True)) # will return here
for nxt in graph[node]:
if color[nxt] == WHITE:
stack.append((nxt, False))
return result[::-1]Comparaison entre DFS et l’algorithme de Kahn
Les deux s’exécutent en O(V + E). Principales différences : l’algorithme de Kahn (BFS) produit naturellement les sommets dans l’ordre des dépendances les plus en amont et offre une détection des cycles plus simple, fondée sur une vérification de longueur. Le postordre de DFS fonctionne de manière récursive et détecte explicitement les arêtes arrière. L’algorithme de Kahn est préférable lorsque vous voulez obtenir le résultat dans l’ordre direct, sans inversion. DFS est préférable lorsque vous avez besoin du postordre complet à d’autres fins, comme la détection des SCC. Les deux conviennent aux entretiens.
Postordre sur un arbre et un DAG
Dans un arbre, le postordre parcourt le sous-arbre gauche → le sous-arbre droit → la racine. Dans un DAG, le DFS en postordre visite toutes les dépendances d’un sommet avant de traiter le sommet lui-même — c’est la même idée généralisée à plusieurs prédécesseurs et à une structure de graphe arbitraire. La racine d’un arbre DFS, c’est-à-dire le sommet de départ, est empilée après tous ses descendants, ce qui la fait apparaître en premier dans la pile inversée — la position topologique correcte pour un sommet sans prédécesseurs.
Dictionnaire extraterrestre (LeetCode 269)
Dictionnaire extraterrestre : étant donné une liste triée de mots dans une langue extraterrestre, déduisez l’ordre des caractères. Comparez les mots adjacents caractère par caractère pour trouver la première différence — cela donne une arête c1 → c2, ce qui signifie que le premier caractère précède le second. Recueillez toutes ces arêtes et exécutez un tri topologique pour produire l’ordre des caractères extraterrestres. Si un cycle existe, l’ordre est invalide.
from collections import defaultdict
def alienOrder(words):
graph = defaultdict(set)
all_chars = set(c for w in words for c in w)
for i in range(len(words)-1):
w1, w2 = words[i], words[i+1]
if len(w1) > len(w2) and w1.startswith(w2):
return '' # invalid (prefix comes after)
for c1, c2 in zip(w1, w2):
if c1 != c2:
graph[c1].add(c2)
break
# DFS topological sort on character graph
WHITE, GREY, BLACK = 0, 1, 2
color = {c: WHITE for c in all_chars}
result = []
def dfs(c):
color[c] = GREY
for nxt in graph[c]:
if color[nxt] == GREY: return False
if color[nxt] == WHITE and not dfs(nxt): return False
color[c] = BLACK
result.append(c)
return True
for c in all_chars:
if color[c] == WHITE:
if not dfs(c): return ''
return ''.join(result[::-1])
print(alienOrder(['wrt','wrf','er','ett','rftt'])) # 'wertf'Tri topologique avec contraintes
Certains problèmes demandent un tri topologique respectant des contraintes supplémentaires, comme le maintien de l’ordre relatif des éléments de la liste d’origine. Combinez l’algorithme de Kahn avec une file de priorité personnalisée ou un pré-tri : conservez l’ordre relatif d’origine des éléments en effectuant un tri stable du contenu de la file d’attente à chaque étape. Ces variantes sous contrainte évaluent une compréhension plus approfondie de la souplesse de l’algorithme.
Reconnaître les problèmes de tri topologique
Voici des expressions indicatrices dans les problèmes d’entretien qui signalent un tri topologique : « dépendances fournies », « prérequis », « ordre des tâches », « ordre de construction », « toutes les tâches peuvent-elles être terminées ? », « trouver une séquence valide ». Si le problème implique un ordre entre des éléments dont certains doivent précéder les autres, construisez un graphe orienté et appliquez le tri topologique de Kahn ou de DFS. La détection des cycles constitue souvent une exigence secondaire du même problème.
Comparaison des sorties de DFS et de Kahn
DFS et l’algorithme de Kahn peuvent produire des ordres topologiques valides différents pour un même graphe. Les deux sont corrects : un DAG peut posséder plusieurs ordres topologiques valides. Pour vérifier la validité, assurez-vous que, pour chaque arc u → v du graphe, le sommet de départ apparaît avant le sommet d’arrivée dans l’ordre de sortie. Pour les problèmes d’entretien qui exigent un ordre précis, par exemple l’ordre lexicographiquement le plus petit, utilisez Kahn avec un tas min : le postordre de DFS ne produit pas naturellement l’ordre lexicographiquement minimal.
Vérification rapide
Testez votre compréhension des concepts de Structures de données et algorithmes & Préparation aux entretiens de programmation présentés dans cette leçon.
Récapitulatif de la leçon
Dans cette leçon, vous avez appris que le tri topologique en postordre de DFS empile les sommets après l’exploration de toutes leurs dépendances, que le marquage à trois couleurs (WHITE/GREY/BLACK) détecte les cycles via les arêtes arrière vers les sommets GREY et que l’inversion de la pile de postordre produit un ordre topologique valide. Nous allons ensuite appliquer directement le tri topologique aux problèmes Planification des cours I et II.
Questions Fréquemment Posées
La leçon « Tri topologique par DFS en post-ordre » est-elle gratuite ?
Oui — le texte complet de « Tri topologique par DFS en post-ordre » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Coding Interview Prep, passe à CoddyKit PRO. Le cours Coding Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Tri topologique par DFS en post-ordre » ?
Exécutez DFS et empilez chaque nœud une fois ses voisins entièrement explorés, puis dépilez la pile pour obtenir un ordre topologique valide. Tu pratiques Coding Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Coding Interview Prep ?
Aucune expérience préalable n'est requise. Coding Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Tri topologique par DFS en post-ordre » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Coding Interview Prep ?
Oui. Chaque leçon Coding Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Algorithme de Kahn : tri topologique par BFS
- Tri topologique par DFS en post-ordre
- Planification de cours I et II
- Composantes fortement connexes avec Kosaraju