🕸️

Graphes

Représentations, parcours BFS/DFS, Dijkstra

Graphes orientés BFS / DFS Dijkstra

🎯 Introduction

Un graphe est un ensemble de sommets (nœuds) reliés par des arêtes (arcs si orienté). Les graphes modélisent les réseaux routiers, sociaux, Internet, les dépendances entre tâches...

✅ Ce qu'il faut savoir

  • Deux représentations : matrice d'adjacence et liste d'adjacence
  • Différence graphe orienté / non orienté / pondéré
  • BFS (parcours en largeur) avec une file
  • DFS (parcours en profondeur) avec récursion ou pile
  • Algorithme de Dijkstra (plus courts chemins, poids positifs)
  • Notions : connexité, cycle, chemin

📐 Représentations

Chaque sommet est associé à la liste de ses voisins. Efficace pour les graphes creux.

# Graphe non orienté
graphe = {
    'A': ['B', 'C'],
    'B': ['A', 'D'],
    'C': ['A', 'D'],
    'D': ['B', 'C']
}

# Graphe pondéré orienté
graphe_p = {
    'A': [('B', 4), ('C', 2)],
    'B': [('D', 5)],
    'C': [('B', 1), ('D', 8)],
    'D': []
}
OpérationComplexité
Voisins d'un sommetO(degré)
Tester si arête (u,v)O(degré)
Espace mémoireO(V + E)

Matrice n×n : M[i][j] = 1 si arête de i vers j. Efficace pour les graphes denses.

# Graphe avec 4 sommets : 0,1,2,3
matrice = [
    [0, 1, 1, 0],   # 0 → 1, 0 → 2
    [1, 0, 0, 1],   # 1 → 0, 1 → 3
    [1, 0, 0, 1],   # 2 → 0, 2 → 3
    [0, 1, 1, 0]    # 3 → 1, 3 → 2
]
# Tester l'arête (0, 1) :
matrice[0][1] == 1   # True — O(1)
OpérationComplexité
Tester si arête (u,v)O(1)
Voisins d'un sommetO(V)
Espace mémoireO(V²)

🔄 Parcours : BFS et DFS

from collections import deque

# BFS — Parcours en Largeur (Breadth-First Search)
# Utilise une FILE. Trouve le plus court chemin (non pondéré).
def bfs(graphe, depart):
    visites = {depart}
    file = deque([depart])
    while file:
        s = file.popleft()
        print(s)
        for voisin in graphe[s]:
            if voisin not in visites:
                visites.add(voisin)
                file.append(voisin)

# DFS — Parcours en Profondeur (Depth-First Search)
# Utilise la RÉCURSION (ou une pile). Explore le plus loin possible.
def dfs(graphe, s, visites=None):
    if visites is None: visites = set()
    visites.add(s)
    print(s)
    for voisin in graphe[s]:
        if voisin not in visites:
            dfs(graphe, voisin, visites)
    return visites
BFSDFS
StructureFile (deque)Récursion / pile
Plus court chemin✅ Oui (non pondéré)❌ Non
Détection de cycle✅ Oui✅ Oui
ComplexitéO(V + E)O(V + E)

🗺️ Algorithme de Dijkstra

⚠️

Condition d'utilisation

Dijkstra ne fonctionne qu'avec des poids positifs ou nuls. Pour les poids négatifs, utiliser Bellman-Ford.

import heapq

def dijkstra(graphe, depart):
    # graphe[s] = [(voisin, poids), ...]
    dist = {s: float('inf') for s in graphe}
    dist[depart] = 0
    tas = [(0, depart)]
    while tas:
        d, u = heapq.heappop(tas)
        if d > dist[u]: continue  # entrée obsolète
        for v, poids in graphe[u]:
            nd = dist[u] + poids
            if nd < dist[v]:
                dist[v] = nd
                heapq.heappush(tas, (nd, v))
    return dist

📌 Propriétés importantes

PropriétéDéfinitionTest
ConnexeTout sommet est atteignable depuis n'importe quel autreBFS/DFS depuis un sommet visite tous les sommets
AcycliquePas de cycle (chemin qui revient au départ)DFS sans marquer → si on revisite → cycle
DAGDirected Acyclic Graph : orienté et sans cycleTri topologique possible
ArbreConnexe et acycliquen sommets, n-1 arêtes
🚨

Pièges du bac

  • Oublier de marquer les sommets comme visités → boucle infinie
  • Confondre BFS (file) et DFS (pile/récursion)
  • Dijkstra avec poids négatifs → résultats faux
  • Pour un graphe non orienté, chaque arête apparaît deux fois dans la liste d'adjacence

🏋️ Exercices

IntermédiaireDétection de cycle

Écrire une fonction qui détecte si un graphe non orienté contient un cycle, en utilisant DFS.

✅ Correction
def a_un_cycle(graphe):
    visites = set()
    def dfs(s, parent):
        visites.add(s)
        for v in graphe[s]:
            if v not in visites:
                if dfs(v, s): return True
            elif v != parent:  # visite d'un voisin déjà vu ≠ parent
                return True
        return False
    for s in graphe:
        if s not in visites:
            if dfs(s, None): return True
    return False

📌 Fiche synthèse

REPRÉSENTATIONS

  • Liste adj : O(V+E) mémoire
  • Matrice : O(V²) mémoire
  • Matrice → test arête O(1)
  • Liste → voisins O(degré)

PARCOURS

  • BFS : file, plus court chemin
  • DFS : récursion / pile
  • Complexité : O(V + E)
  • Toujours marquer les visités !

DIJKSTRA

  • Poids positifs uniquement
  • Utilise un tas-min (heapq)
  • O((V+E) log V)
  • Plus court depuis source

🧠 QCM

Choisissez le nombre de questions et le niveau, puis lancez.

← Arbres POO →