Leçon 17 sur 19

Chapitre 17 — Parcours de graphes

Explorer, marquer, rechercher des chemins et analyser les composantes d’un réseau

DFS  →   PILE / RÉCURSIVITÉ  →  BFS   →  FILE  →   CHEMINS  →  COMPOSANTES

 

Fiche pédagogique du chapitre

Objectifs d’apprentissage

À la fin de ce chapitre, l’étudiant devra être capable de :

• expliquer le principe du parcours en profondeur et du parcours en largeur ;

• implémenter un DFS récursif et un DFS itératif avec une pile ;

• implémenter un BFS avec une file ;

• utiliser un tableau de marquage pour éviter les répétitions et les boucles infinies ;

• construire une forêt de parcours et identifier les composantes connexes ;

• rechercher un chemin et reconstruire ce chemin à l’aide des prédécesseurs ;

• calculer des distances minimales dans un graphe non pondéré ;

• appliquer les parcours à la connexité, aux labyrinthes et à la détection de cycles ;

• analyser la complexité temporelle et spatiale des parcours.

Prérequis

• représentation des graphes par listes ou matrices d’adjacence ;

• piles, files et récursivité ;

• tableaux, listes et dictionnaires ;

• notions de chemin, cycle, degré et composante ;

• complexité en O(n + m).

Organisation indicative

Activité

Volume conseillé

Finalité

Cours4 à 5 hComprendre DFS, BFS et leurs invariants.
Travaux dirigés4 hTracer les parcours et résoudre des problèmes de graphes.
Travaux pratiques5 à 7 hImplémenter et instrumenter les parcours.
Évaluation1 à 2 hChoix de parcours, correction et analyse.

 

Idée directrice

Un parcours explore les sommets accessibles à partir d’un point de départ. La stratégie de stockage des sommets à traiter détermine l’ordre de l’exploration.

• Une pile ou la récursivité produit une exploration en profondeur.

• Une file produit une exploration niveau par niveau.

• Le marquage garantit qu’un sommet n’est traité qu’une seule fois.

 

Introduction générale

La représentation d’un graphe décrit quelles relations existent. Un parcours exploite cette représentation pour visiter méthodiquement les sommets et les arêtes. Les deux parcours fondamentaux sont le parcours en profondeur, souvent noté DFS, et le parcours en largeur, souvent noté BFS.

Ces parcours constituent la base de nombreux algorithmes : recherche d’un chemin, calcul de distances non pondérées, détection de connexité, construction de composantes, exploration de labyrinthes, détection de cycles et analyse de dépendances.

Figure 17.1 — Graphe non orienté utilisé comme exemple fil rouge.

Convention adoptée

Lorsque plusieurs voisins sont disponibles, ils sont examinés dans l’ordre alphabétique. Un autre ordre reste correct, mais il peut produire un arbre de parcours et un ordre de visite différents.

 

17.1 Parcours en profondeur

17.1.1 Principe général

Le parcours en profondeur explore une branche aussi loin que possible avant de revenir au dernier sommet possédant encore un voisin non visité. Ce retour en arrière est naturellement géré par la pile d’appels récursifs ou par une pile explicite.

1. Marquer le sommet courant comme visité.

2. Traiter le sommet selon le besoin de l’application.

3. Choisir un voisin non visité et poursuivre l’exploration.

4. Revenir en arrière lorsque tous les voisins ont été examinés.

17.1.2 Marquage des sommets

Sans marquage, un algorithme pourrait revisiter indéfiniment les mêmes sommets lorsqu’un cycle existe. Un tableau Visite, indexé par sommet, mémorise les sommets déjà découverts.

État

Signification

Utilisation

Non visitéLe sommet n’a pas encore été découvert.Il peut être ajouté à la pile ou visité récursivement.
DécouvertLe sommet est en cours d’exploration.Utile pour les cycles dans les graphes orientés.
TerminéTous les voisins ont été traités.Permet une analyse plus fine des arcs.

 

Invariant fondamental

À tout instant, chaque sommet marqué possède un chemin depuis le sommet de départ constitué uniquement de sommets déjà découverts. Le marquage est effectué avant l’exploration des voisins.

 

17.1.3 Version récursive

ZONE DE PSEUDO-CODE — DFS récursif depuis un sommet

Procédure DFS_Recursif(G, u, Visite, Parent)

    Visite[u] ← Vrai

    Traiter(u)

    Pour chaque voisin v de u Faire

        Si NON Visite[v] Alors

            Parent[v] ← u

            DFS_Recursif(G, v, Visite, Parent)

        FinSi

    FinPour

FinProcédure

La pile des appels mémorise automatiquement les sommets auxquels il faudra revenir.

 

ZONE DE PSEUDO-CODE — Initialiser un DFS

Procédure LancerDFS(G, source)

    Pour chaque sommet u de G Faire

        Visite[u] ← Faux

        Parent[u] ← AUCUN

    FinPour

    DFS_Recursif(G, source, Visite, Parent)

FinProcédure

Cette version n’explore que la composante contenant la source.

 

Trace sur le graphe fil rouge

Depuis A et avec des voisins examinés par ordre alphabétique, un ordre possible est : A, B, C, E, D, F. La structure exacte dépend de l’ordre des voisins dans les listes d’adjacence.

Étape

Sommet courant

Action

Pile d’appels simplifiée

1AMarquer A puis choisir BA
2BMarquer B puis choisir CA → B
3CMarquer C puis choisir EA → B → C
4EMarquer E puis choisir DA → B → C → E
5DMarquer D puis choisir FA → B → C → E → D
6FMarquer F ; aucun voisin nouveauA → B → C → E → D → F
7Retours successifsD → E → C → B → A

 

17.1.4 Version itérative avec une pile

Une pile explicite évite la dépendance à la profondeur maximale de récursion. Deux variantes existent : marquer un sommet lors de son empilement ou lors de son dépilement. Le marquage à l’empilement évite les insertions multiples.

ZONE DE PSEUDO-CODE — DFS itératif avec marquage à l’empilement

Procédure DFS_Iteratif(G, source)

    Pour chaque sommet u de G Faire

        Visite[u] ← Faux

        Parent[u] ← AUCUN

    FinPour

    Créer une pile P vide

    Empiler(P, source)

    Visite[source] ← Vrai

    TantQue P n’est pas vide Faire

        u ← Dépiler(P)

        Traiter(u)

        Pour chaque voisin v de u dans l’ordre inverse Faire

            Si NON Visite[v] Alors

                Visite[v] ← Vrai

                Parent[v] ← u

                Empiler(P, v)

            FinSi

        FinPour

    FinTantQue

FinProcédure

L’ordre inverse d’empilement permet de reproduire l’ordre alphabétique du DFS récursif.

 

Critère

DFS récursif

DFS itératif

Structure utiliséePile d’appels du langagePile explicite
LisibilitéSouvent très concisePlus détaillée
RisqueDépassement de pile sur graphe profondMémoire contrôlée explicitement
Informations supplémentairesTemps d’entrée/sortie facilesÉtat explicite à gérer

 

17.1.5 Détection des composantes

Dans un graphe non orienté, un DFS lancé depuis un sommet visite exactement sa composante connexe. Pour traiter tout le graphe, on relance un DFS depuis chaque sommet encore non visité. L’ensemble des arbres obtenus constitue une forêt DFS.

ZONE DE PSEUDO-CODE — Calculer les composantes connexes

Fonction ComposantesConnexes(G) : Entier

    Pour chaque sommet u de G Faire

        Visite[u] ← Faux

    FinPour

    nombre ← 0

    Pour chaque sommet u de G Faire

        Si NON Visite[u] Alors

            nombre ← nombre + 1

            DFS_Recursif(G, u, Visite, Parent)

        FinSi

    FinPour

    Retourner nombre

FinFonction

On peut également associer à chaque sommet le numéro de sa composante.

 

Figure 17.2 — Une forêt DFS contient un arbre par composante connexe.

ZONE DE PSEUDO-CODE — Étiqueter chaque composante

Procédure Etiqueter(G, u, numero, Composante)

    Composante[u] ← numero

    Pour chaque voisin v de u Faire

        Si Composante[v] = 0 Alors

            Etiqueter(G, v, numero, Composante)

        FinSi

    FinPour

FinProcédure

L’étiquette permet ensuite de tester en O(1) si deux sommets appartiennent à la même composante.

 

17.1.6 Complexité du DFS

Représentation

Temps

Mémoire auxiliaire

Liste d’adjacenceO(n + m)O(n) pour marquage, parents et pile
Matrice d’adjacenceO(n²)O(n) en plus de la matrice

 

Avec des listes d’adjacence, chaque sommet est marqué une fois et chaque arête est examinée au plus deux fois dans un graphe non orienté. La profondeur de la pile peut atteindre n dans un graphe en forme de chaîne.

17.2 Parcours en largeur

17.2.1 Principe général

Le parcours en largeur visite les sommets par couches successives : d’abord la source, puis tous ses voisins, ensuite les sommets situés à distance deux, et ainsi de suite. La file garantit que les sommets sont traités dans l’ordre de leur découverte.

1. Enfiler la source et la marquer.

2. Défiler le sommet le plus ancien.

3. Découvrir tous ses voisins encore non visités.

4. Enfiler ces voisins et répéter jusqu’à ce que la file soit vide.

17.2.2 BFS avec une file

ZONE DE PSEUDO-CODE — Parcours en largeur complet depuis une source

Procédure BFS(G, source)

    Pour chaque sommet u de G Faire

        Visite[u] ← Faux

        Distance[u] ← INFINI

        Parent[u] ← AUCUN

    FinPour

    Créer une file F vide

    Visite[source] ← Vrai

    Distance[source] ← 0

    Enfiler(F, source)

    TantQue F n’est pas vide Faire

        u ← Défiler(F)

        Traiter(u)

        Pour chaque voisin v de u Faire

            Si NON Visite[v] Alors

                Visite[v] ← Vrai

                Distance[v] ← Distance[u] + 1

                Parent[v] ← u

                Enfiler(F, v)

            FinSi

        FinPour

    FinTantQue

FinProcédure

Le marquage est effectué avant l’enfilement afin d’éviter qu’un sommet soit ajouté plusieurs fois.

 

Figure 17.3 — Un BFS depuis A organise les sommets par distance minimale.

Sommet

Distance depuis A

Parent possible

Niveau

A0Aucun0
B1A1
C1A1
D2B2
E2C2
F3D ou E3

 

17.2.3 Trace de la file

Étape

Sommet défilé

Nouveaux sommets

Contenu de la file

InitialisationA[A]
1AB, C[B, C]
2BD[C, D]
3CE[D, E]
4DF[E, F]
5EAucun[F]
6FAucun[]

 

Invariant des niveaux

Lorsque le sommet u est défilé, sa distance minimale depuis la source est définitivement connue. Tous les sommets actuellement dans la file ont une distance égale à Distance[u] ou Distance[u] + 1.

 

17.2.4 Distance minimale en nombre d’arêtes

Dans un graphe non pondéré, le BFS calcule le nombre minimal d’arêtes entre la source et chaque sommet accessible. Cette propriété ne s’applique pas directement aux graphes pondérés, sauf lorsque tous les poids sont identiques.

ZONE DE PSEUDO-CODE — Retourner une distance minimale

Fonction DistanceMinimale(G, source, cible) : Entier

    Exécuter BFS(G, source)

    Si Distance[cible] = INFINI Alors

        Retourner -1

    Sinon

        Retourner Distance[cible]

    FinSi

FinFonction

La valeur -1 signale ici que la cible est inaccessible.

 

17.2.5 Reconstruction d’un chemin

Le tableau Parent enregistre le sommet à partir duquel chaque sommet a été découvert. Pour reconstruire le chemin, on part de la cible et on remonte jusqu’à la source, puis on inverse la séquence.

ZONE DE PSEUDO-CODE — Reconstruire le chemin BFS

Fonction ReconstruireChemin(source, cible, Parent) : Liste

    Si cible ≠ source ET Parent[cible] = AUCUN Alors

        Retourner LISTE_VIDE

    FinSi

    chemin ← LISTE_VIDE

    courant ← cible

    TantQue courant ≠ AUCUN Faire

         AjouterEnTete(chemin, courant)

        Si courant = source Alors

            Retourner chemin

        FinSi

        courant ← Parent[courant]

    FinTantQue

    Retourner LISTE_VIDE

FinFonction

Avec les parents produits ci-dessus, un chemin de A vers F peut être A → B → D → F.

 

17.2.6 BFS sur un graphe non connexe

Comme le DFS, un BFS lancé depuis une seule source reste limité à sa composante. Pour parcourir tout le graphe, on relance un BFS depuis chaque sommet non visité.

ZONE DE PSEUDO-CODE — Forêt BFS

Procédure ParcourirToutParBFS(G)

    Initialiser tous les sommets comme non visités

    Pour chaque sommet u de G Faire

        Si NON Visite[u] Alors

             BFS_Composante(G, u, Visite)

        FinSi

    FinPour

FinProcédure

Chaque lancement construit un arbre BFS dans une composante différente.

 

17.2.7 Complexité du BFS

Représentation

Temps

Mémoire auxiliaire

Liste d’adjacenceO(n + m)O(n) pour la file, les distances et les parents
Matrice d’adjacenceO(n²)O(n) en plus de la matrice

 

17.2.8 Comparaison DFS / BFS

Critère

DFS

BFS

StructurePile ou récursivitéFile
OrdreProfondeur avant retourNiveau par niveau
Chemin non pondéré minimalNon garantiGaranti
Mémoire sur graphe largeDépend de la profondeurPeut stocker un niveau très large
Applications naturellesCycles, composantes, ordre de finDistances, niveaux, chemin court
Complexité avec listesO(n + m)O(n + m)

 

17.3 Applications

17.3.1 Recherche d’un chemin

Pour savoir si un chemin existe entre s et t, un DFS ou un BFS suffit. Si l’on veut un chemin comportant un nombre minimal d’arêtes, on utilise un BFS. Pour obtenir un chemin quelconque, les deux méthodes conviennent.

ZONE DE PSEUDO-CODE — Existe-t-il un chemin ?

Fonction ExisteChemin(G, s, t) : Booléen

    Exécuter DFS ou BFS depuis s

    Retourner Visite[t]

FinFonction

L’arrêt peut être anticipé dès que t est découvert.

 

ZONE DE PSEUDO-CODE — BFS avec arrêt anticipé

Fonction ChercherCheminCourt(G, s, t) : Liste

    Initialiser Visite, Parent et une file F

    Marquer s puis Enfiler(F, s)

    TantQue F n’est pas vide Faire

        u ← Défiler(F)

        Pour chaque voisin v de u Faire

            Si NON Visite[v] Alors

                Visite[v] ← Vrai

                Parent[v] ← u

                Si v = t Alors

                     Retourner ReconstruireChemin(s, t, Parent)

                FinSi

                Enfiler(F, v)

            FinSi

        FinPour

    FinTantQue

    Retourner LISTE_VIDE

FinFonction

 

17.3.2 Détection de connexité

Un graphe non orienté est connexe si un parcours lancé depuis n’importe quel sommet visite les n sommets. Pour un graphe vide, la convention doit être précisée.

ZONE DE PSEUDO-CODE — Tester la connexité

Fonction EstConnexe(G) : Booléen

    Si G ne contient aucun sommet Alors

        Retourner Vrai

    FinSi

    Choisir un sommet s

    Exécuter DFS(G, s)

    Pour chaque sommet u de G Faire

        Si NON Visite[u] Alors

            Retourner Faux

        FinSi

    FinPour

    Retourner Vrai

FinFonction

 

Graphe orienté

Dans un graphe orienté, être accessible depuis une source ne suffit pas à conclure à la forte connexité. Il faut vérifier l’accessibilité dans les deux sens, ce qui conduit à des algorithmes étudiés au niveau avancé.

 

17.3.3 Exploration d’un labyrinthe

Une grille peut être vue comme un graphe implicite : chaque case libre est un sommet et deux cases voisines sont reliées lorsqu’un déplacement est autorisé. Le BFS trouve un chemin comportant un nombre minimal de déplacements ; le DFS trouve un chemin éventuel sans garantir qu’il soit court.

Figure 17.4 — Exemple de chemin dans une grille ; chaque case libre représente un sommet.

ZONE DE PSEUDO-CODE — Générer les voisins d’une case

Fonction VoisinsGrille(grille, ligne, colonne) : Liste

    directions ← [(-1,0), (1,0), (0,-1), (0,1)]

    resultat ← LISTE_VIDE

    Pour chaque (dl, dc) dans directions Faire

        l2 ← ligne + dl

        c2 ← colonne + dc

        Si (l2,c2) est dans la grille ET grille[l2][c2] est libre Alors

            Ajouter (l2,c2) à resultat

        FinSi

    FinPour

    Retourner resultat

FinFonction

 

ZONE DE PSEUDO-CODE — Résoudre un labyrinthe avec BFS

Fonction ResoudreLabyrinthe(grille, depart, arrivee) : Liste

    Effectuer un BFS depuis depart en générant les voisins à la demande

    Si arrivee n’est pas visitée Alors

        Retourner LISTE_VIDE

    FinSi

    Retourner ReconstruireChemin(depart, arrivee, Parent)

FinFonction

La complexité est proportionnelle au nombre de cases libres et de relations entre cases.

 

17.3.4 Détection simple d’un cycle

Cycle dans un graphe non orienté

Lors d’un DFS, rencontrer un voisin déjà visité ne prouve pas toujours un cycle : ce voisin peut être le parent du sommet courant. Un cycle existe lorsque l’on rencontre un voisin visité différent du parent.

ZONE DE PSEUDO-CODE — Détecter un cycle non orienté

Fonction CycleNonOriente(G, u, parent, Visite) : Booléen

    Visite[u] ← Vrai

    Pour chaque voisin v de u Faire

        Si NON Visite[v] Alors

            Si CycleNonOriente(G, v, u, Visite) Alors

                Retourner Vrai

            FinSi

        SinonSi v ≠ parent Alors

            Retourner Vrai

        FinSi

    FinPour

    Retourner Faux

FinFonction

Pour un graphe non connexe, la fonction doit être lancée depuis chaque composante non visitée.

 

Cycle dans un graphe orienté

Dans un graphe orienté, on utilise trois couleurs : blanc pour non visité, gris pour en cours d’exploration et noir pour terminé. Un arc vers un sommet gris révèle un cycle dirigé.

ZONE DE PSEUDO-CODE — Détecter un cycle orienté par couleurs

Fonction CycleOriente(G, u, Couleur) : Booléen

    Couleur[u] ← GRIS

    Pour chaque successeur v de u Faire

        Si Couleur[v] = GRIS Alors

            Retourner Vrai

        SinonSi Couleur[v] = BLANC Alors

            Si CycleOriente(G, v, Couleur) Alors

                Retourner Vrai

            FinSi

        FinSi

    FinPour

    Couleur[u] ← NOIR

    Retourner Faux

FinFonction

 

17.3.5 Calcul des composantes connexes

Une composante connexe est un ensemble maximal de sommets reliés entre eux par des chemins. Le nombre de lancements de DFS ou de BFS nécessaires pour visiter tout le graphe est égal au nombre de composantes.

ZONE DE PSEUDO-CODE — Retourner les listes de composantes

Fonction ListerComposantes(G) : ListeDeListes

    Initialiser Visite à Faux

    composantes ← LISTE_VIDE

    Pour chaque sommet u de G Faire

        Si NON Visite[u] Alors

            courante ← LISTE_VIDE

             ExplorerEtCollecter(G, u, Visite, courante)

            Ajouter courante à composantes

        FinSi

    FinPour

    Retourner composantes

FinFonction

 

ZONE DE PSEUDO-CODE — DFS qui collecte les sommets

Procédure ExplorerEtCollecter(G, u, Visite, courante)

    Visite[u] ← Vrai

    Ajouter u à courante

    Pour chaque voisin v de u Faire

        Si NON Visite[v] Alors

             ExplorerEtCollecter(G, v, Visite, courante)

        FinSi

    FinPour

FinProcédure

 

Méthode de choix entre DFS et BFS

Besoin

Parcours conseillé

Justification

Atteindre tous les sommetsDFS ou BFSMême complexité asymptotique.
Chemin avec peu d’arêtesBFSExploration par niveaux.
Détection de cycle orientéDFSUtilisation des états gris/noir.
Composantes connexesDFS ou BFSUn lancement par composante.
Exploration profonde avec mémoire limitéeDFSPile proportionnelle à la profondeur.
Distance non pondéréeBFSPremière découverte optimale.

 

Attention aux poids

Le BFS ne calcule un plus court chemin que lorsque toutes les arêtes ont le même coût. Avec des poids positifs différents, on utilisera notamment l’algorithme de Dijkstra.

 

Erreurs fréquentes et bonnes pratiques

Erreur

Conséquence

Bonne pratique

Marquer au dépilement ou au défilementAjouts multiples dans la structureMarquer dès la découverte.
Réutiliser un tableau Visite non réinitialiséSommets ignorésRéinitialiser pour un nouveau parcours indépendant.
Oublier les composantes non accessiblesParcours incompletBoucler sur tous les sommets.
Confondre parent et voisin visitéFaux cycle non orientéIgnorer uniquement l’arête vers le parent.
Utiliser BFS sur poids variablesDistance incorrecteChoisir un algorithme pondéré.
Supposer un ordre de visite uniqueTests fragilesComparer les propriétés, ou fixer l’ordre des voisins.
DFS récursif sur une chaîne immenseDépassement de pilePréférer une pile explicite.

 

Bonnes pratiques de conception

• séparer la structure du graphe de l’algorithme de parcours ;

• rendre explicite l’ordre des voisins lorsque le résultat doit être reproductible ;

• conserver les parents lorsque l’application demande un chemin ;

• conserver les distances uniquement lorsqu’elles sont utiles ;

• prévoir le cas d’une source absente ou d’un graphe vide ;

• tester les graphes isolés, cycliques, en chaîne, en étoile et non connexes ;

• instrumenter le nombre de sommets et d’arêtes examinés pour valider l’analyse.

Travaux dirigés

Les exercices suivants supposent que les voisins sont examinés par ordre alphabétique, sauf indication contraire.

TD 1 — Tracer un DFS

• Donner l’ordre du DFS récursif du graphe fil rouge depuis A.

• Construire le tableau Parent.

• Dessiner l’arbre DFS obtenu.

TD 2 — Tracer un BFS

• Donner l’ordre du BFS depuis A.

• Compléter les distances et les parents.

• Reconstituer un chemin minimal de A vers F.

TD 3 — Ordres de voisinage

• Reprendre le DFS avec des voisins examinés dans l’ordre inverse.

• Comparer l’ordre de visite et l’ensemble des sommets atteints.

• Expliquer ce qui reste invariant.

TD 4 — Graphe non connexe

• Pour le graphe composé de {A,B,C,D}, {E,F} et {G}, déterminer le nombre de composantes.

• Donner une forêt de parcours possible.

TD 5 — Recherche de chemin

• Proposer un algorithme qui s’arrête dès que la cible est découverte.

• Préciser comment reconstruire le chemin.

TD 6 — Cycle non orienté

• Expliquer pourquoi l’arête vers le parent doit être ignorée.

• Appliquer l’algorithme à un triangle puis à une chaîne.

TD 7 — Cycle orienté

• Appliquer la méthode des trois couleurs à A→B, B→C, C→A.

• Appliquer-la à A→B, A→C, B→D, C→D.

TD 8 — Labyrinthe

• Modéliser une grille 4×4 contenant des obstacles.

• Indiquer les voisins d’une case intérieure et d’une case de bord.

• Choisir DFS ou BFS pour obtenir un trajet minimal.

TD 9 — Analyse de complexité

• Justifier O(n+m) pour un BFS sur listes d’adjacence.

• Expliquer pourquoi une matrice conduit à O(n²).

TD 10 — Choix de méthode

• Choisir DFS ou BFS pour : distance sociale, détection d’un cycle dirigé, composantes et recherche d’un chemin quelconque.

• Justifier chaque choix.

Corrigés indicatifs des travaux dirigés

Correction du TD 1

Un ordre possible est A, B, C, E, D, F. Les parents possibles sont Parent[B]=A, Parent[C]=B, Parent[E]=C, Parent[D]=E et Parent[F]=D. Un autre ordre reste valide si l’ordre des voisins diffère.

Correction du TD 2

L’ordre BFS est A, B, C, D, E, F. Les distances sont 0, 1, 1, 2, 2 et 3. Un chemin minimal est A→B→D→F ; A→C→E→F est également minimal.

Correction du TD 3

L’ordre de visite et l’arbre de parcours changent. L’ensemble des sommets accessibles, la complexité et le fait que chaque sommet soit visité une fois restent invariants.

Correction du TD 4

Le graphe possède trois composantes. La forêt contient un arbre sur {A,B,C,D}, un arbre sur {E,F} et un arbre réduit au sommet isolé G.

Correction du TD 5

Un BFS avec arrêt à la découverte de la cible fournit un chemin minimal non pondéré. Le tableau Parent permet de remonter de la cible vers la source, puis d’inverser le résultat.

Correction du TD 6

Dans un graphe non orienté, chaque arête apparaît dans les deux sens. Le parent est donc toujours un voisin déjà visité. Le triangle contient un cycle, tandis que la chaîne n’en contient pas.

Correction du TD 7

Dans le premier graphe, l’arc C→A atteint un sommet gris : un cycle existe. Dans le second, aucun arc ne pointe vers un sommet gris ; le graphe est acyclique.

Correction du TD 8

Chaque case libre est reliée à ses voisines libres orthogonales. Une case intérieure peut avoir quatre voisins et une case de bord au plus trois. Le BFS est choisi pour minimiser le nombre de déplacements.

Correction du TD 9

Avec les listes, chaque sommet et chaque entrée d’adjacence sont examinés une fois : O(n+m). Avec une matrice, l’algorithme examine n cases pour chacun des n sommets : O(n²).

Correction du TD 10

Problème

Choix

Justification

Distance socialeBFSDistance minimale en nombre d’arêtes.
Cycle dirigéDFSÉtats blanc, gris et noir.
ComposantesDFS ou BFSUn parcours par composante.
Chemin quelconqueDFS ou BFSLes deux testent l’accessibilité.

 

Travail pratique — Bibliothèque de parcours de graphes

Objectif

Développer une bibliothèque capable d’exécuter DFS et BFS sur une représentation par listes d’adjacence, puis de résoudre plusieurs problèmes classiques.

Fonctionnalités attendues

• ajouter et supprimer des sommets et des arêtes ;

• exécuter un DFS récursif et un DFS itératif ;

• exécuter un BFS et retourner les distances et les parents ;

• reconstruire un chemin entre deux sommets ;

• tester la connexité et lister les composantes connexes ;

• détecter un cycle dans un graphe non orienté ;

• charger un graphe depuis un fichier texte ;

• mesurer le nombre de sommets et d’arêtes examinés.

Organisation recommandée

ZONE DE PSEUDO-CODE — Interface du module Parcours

DFS_Recursif(G, source) → ordre, parent

DFS_Iteratif(G, source) → ordre, parent

BFS(G, source) → ordre, distance, parent

ReconstruireChemin(source, cible, parent) → liste

ComposantesConnexes(G) → liste de composantes

ContientCycleNonOriente(G) → booléen

Chaque fonction doit documenter ses préconditions et ses résultats.

 

Étapes de réalisation

1. Implémenter ou réutiliser un TAD Graphe par listes d’adjacence.

2. Écrire les versions DFS et vérifier l’absence de visites multiples.

3. Écrire le BFS avec distances et parents.

4. Ajouter la reconstruction des chemins.

5. Ajouter les composantes connexes et la détection de cycles.

6. Créer des tests unitaires et comparer les ordres obtenus.

7. Mesurer les opérations sur des graphes de tailles croissantes.

Jeux d’essai obligatoires

Graphe

Propriété attendue

Vérifications

VideAucun parcoursGestion sans erreur
Un sommetUne composanteDistance 0 depuis lui-même
ChaîneConnexe et sans cycleDistances croissantes
TriangleConnexe et cycliqueCycle détecté
ÉtoileLarge niveau BFSTous les voisins à distance 1
Deux composantesNon connexeDeux listes distinctes
Sommet isoléComposante singletonAucun voisin

 

Grille d’évaluation

Critère

Points

Structure du graphe et robustesse3
DFS récursif et itératif4
BFS, distances et parents4
Chemins et composantes3
Détection de cycle2
Tests et mesures2
Qualité du code et documentation2

 

Synthèse du chapitre

Concept

Idée essentielle

DFSExplore une branche à fond ; utilise une pile ou la récursivité.
BFSExplore par niveaux ; utilise une file.
MarquageEmpêche les visites répétées et les boucles infinies.
ParentPermet de construire un arbre de parcours et de reconstruire un chemin.
Distance BFSNombre minimal d’arêtes depuis la source dans un graphe non pondéré.
ComposanteEnsemble maximal de sommets mutuellement reliés dans un graphe non orienté.
ComplexitéO(n+m) avec des listes d’adjacence.

 

À retenir

Le choix entre DFS et BFS ne dépend pas uniquement de la complexité, souvent identique, mais surtout de l’information recherchée et de l’ordre d’exploration nécessaire.

 

Glossaire

Terme

Définition

DécouvertePremière rencontre d’un sommet non visité.
Arbre de parcoursArbre formé par les relations Parent.
Forêt de parcoursEnsemble des arbres produits sur un graphe non connexe.
NiveauDistance BFS depuis la source.
Composante connexeSous-ensemble maximal de sommets reliés.
Arc de retourArc vers un ancêtre en cours d’exploration ; signe d’un cycle orienté.

 

Auto-évaluation

Je suis capable de…

Oui

À revoir

expliquer la différence entre DFS et BFS
écrire un DFS récursif et itératif
écrire un BFS avec distances et parents
reconstruire un chemin
calculer les composantes connexes
détecter un cycle non orienté simple
choisir un parcours adapté à une application
justifier la complexité O(n+m)

 

Fin du chapitre 17 — Parcours de graphes