Menu
Coddy logo textTech

Parcours en profondeur (DFS)

Dernière mise à jour

Le parcours en profondeur explore un graphe en allant le plus loin possible le long de chaque branche avant de revenir en arrière. En partant d'un nœud source, il visite un voisin, puis le voisin de ce voisin, et ainsi de suite jusqu'à atteindre une impasse (un nœud sans voisin non visité), moment auquel il revient en arrière et essaie la branche suivante. Appuyez sur lecture ci-dessus pour le voir descendre le long d'un chemin, atteindre le fond et remonter.

Le DFS s'exprime naturellement avec une pile : soit une pile explicite (comme animée ici), soit la pile d'appels via la récursion. Il visite chaque nœud et chaque arête une fois, donc il s'exécute en temps O(V + E) pour un graphe à V sommets et E arêtes.

Complexité en temps et en espace

MesureComplexitéRemarques
TempsO(V + E)Chaque sommet et arête visité une fois
EspaceO(V)Pile + ensemble des visités, au pire tous les nœuds
ParcoursLe plus profond d'abordSuit une branche jusqu'au bout avant les autres
Structure de donnéesPile (ou récursion)L'ordre LIFO pilote le comportement en profondeur

Étape par étape

ÉtapeCe qui se passe
1Empiler le nœud source sur la pile.
2Dépiler un nœud ; s'il est déjà visité, le sauter.
3Le marquer comme visité et enregistrer l'arête qui l'a atteint.
4Empiler tous ses voisins non visités.
5Répéter jusqu'à ce que la pile soit vide.

Exemple détaillé

DFS itératif depuis A sur le graphe A → [B, C], B → [D], C → [E], en empilant les voisins dans l'ordre indiqué (la pile LIFO dépile d'abord le dernier empilé) :

ÉtapePile (sommet à droite)VisitésAction
1[A]{}Empiler la source A.
2[B, C]{A}Dépiler A, marquer visité, empiler les voisins B puis C.
3[B, E]{A, C}Dépiler C, marquer visité, empiler le voisin E.
4[B]{A, C, E}Dépiler E, marquer visité, aucun voisin.
5[D]{A, C, E, B}Dépiler B, marquer visité, empiler le voisin D.
6[]{A, C, E, B, D}Dépiler D, marquer visité, pile vide : terminé.

Quand utiliser le DFS

À utiliser quandÀ éviter quand
Vous avez besoin de détecter des cycles, d'un tri topologique ou de trouver les composantes connexes.Vous avez besoin du plus court chemin dans un graphe non pondéré : c'est le BFS qui le fait, pas le DFS.
Le graphe est large et peu profond, donc une pile utilise bien moins de mémoire qu'une file remplie de nombreux nœuds frontière.Le graphe est très profond et vous utilisez la récursion : la pile d'appels peut déborder.
Vous voulez explorer les chemins de manière exhaustive, comme pour résoudre un labyrinthe ou une recherche avec retour arrière.Vous avez besoin de découvrir les nœuds par ordre de distance depuis la source.
Vous vérifiez l'accessibilité ou l'existence d'un chemin entre deux nœuds.Vous devez garantir le nombre minimal d'arêtes sur le chemin trouvé.

Une implémentation propre et exécutable de Depth-First Search en Python, JavaScript, Java, C++, C. Choisissez un langage, copiez le code ou ouvrez-le préchargé dans le Playground Coddy.

Code de Depth-First Search en Python

Python
1def dfs(graph, node, visited):2    visited.add(node)3    order = [node]4    for neighbor in graph[node]:5        if neighbor not in visited:6            order.extend(dfs(graph, neighbor, visited))7    return order8
9
10graph = {11    "A": ["B", "C"],12    "B": ["D", "E"],13    "C": ["F"],14    "D": [],15    "E": ["F"],16    "F": [],17}18
19order = dfs(graph, "A", set())20print("DFS order:", " -> ".join(order))
Exécutez ce code dans le Playground Python

FAQ sur le parcours en profondeur

Quelle est la complexité temporelle du DFS ?
Le DFS s'exécute en temps O(V + E), où V est le nombre de sommets et E le nombre d'arêtes, car il visite chaque sommet une fois et examine chaque arête une fois. Il utilise un espace O(V) pour la pile et l'ensemble des visités.
Quelle est la différence entre DFS et BFS ?
Le DFS utilise une pile et plonge en profondeur le long d'une branche avant de revenir en arrière, tandis que le BFS utilise une file et explore niveau par niveau, les nœuds les plus proches d'abord. Le BFS trouve le plus court chemin dans un graphe non pondéré ; le DFS non, mais il utilise moins de mémoire sur les graphes larges et convient naturellement à des tâches comme la détection de cycles et le tri topologique.
Le DFS est-il récursif ou itératif ?
Les deux fonctionnent. La version récursive utilise implicitement la pile d'appels du programme et est très concise ; la version itérative utilise une pile explicite (comme l'animation ici) et évite les débordements de pile dus à une récursion profonde sur les grands graphes.
Quand dois-je utiliser le DFS plutôt que le BFS ?
Utilisez le DFS quand vous devez explorer des chemins entiers : détection de cycles, tri topologique, composantes connexes ou recherche avec retour arrière comme la résolution d'un labyrinthe. Il utilise aussi moins de mémoire sur les graphes larges, car la pile ne contient que la frontière d'une seule branche à la fois. Optez pour le BFS lorsque vous avez besoin du plus court chemin dans un graphe non pondéré ou des nœuds par ordre de distance depuis la source.
Le DFS peut-il trouver le plus court chemin ?
Pas de façon fiable. Le DFS renvoie le premier chemin qu'il trouve, qui n'est souvent pas celui comptant le moins d'arêtes, car il s'engage à plonger en profondeur plutôt qu'à s'étendre uniformément. Pour les plus courts chemins dans un graphe non pondéré, utilisez le BFS, et pour les graphes pondérés, utilisez l'algorithme de Dijkstra.
Pourquoi le DFS a-t-il besoin d'un ensemble de visités ?
Sans ensemble de visités, le DFS revisitera les nœuds accessibles par plusieurs chemins et, dans un graphe cyclique, bouclera à l'infini. Marquer un nœud comme visité au moment de le dépiler (et sauter les dépilements déjà visités) garantit que chaque nœud est traité une fois et maintient le temps d'exécution à O(V + E). Une erreur fréquente consiste à ne marquer les nœuds comme visités qu'au dépilement tout en continuant d'empiler des doublons, ce qui est correct mais peut laisser des entrées périmées dans la pile qu'il faut sauter.
Coddy programming languages illustration

Maîtrisez les algorithmes avec Coddy

COMMENCER