Algorithmes de graphes : parcours et plus courts chemins
Vidéo disponible dans la version Premium
Durée : 60 min
Algorithmes de graphes : parcours et plus courts chemins
1. Représentation des graphes
Un graphe est constitué d'un ensemble de sommets (taille ) et d'arêtes (taille ), orientées ou non. Deux représentations usuelles : la matrice d'adjacence (tableau , accès à une arête, mais de mémoire — adaptée aux graphes denses) et la liste d'adjacence (pour chaque sommet, la liste de ses voisins, mémoire — adaptée aux graphes creux, cas le plus fréquent en pratique).
2. Parcours en profondeur (DFS)
Le parcours en profondeur (Depth-First Search) explore un graphe en allant aussi loin que possible avant de revenir en arrière (backtracking), à l'aide d'une pile (explicite ou via la récursion). Complexité : (chaque sommet et chaque arête est visité une fois).
DFS(G, s) :
marquer s comme visité
pour chaque voisin v de s non visité :
DFS(G, v)
Applications : détection de cycles, tri topologique d'un graphe orienté acyclique (DAG), recherche des composantes connexes.
3. Parcours en largeur (BFS)
Le parcours en largeur (Breadth-First Search) explore le graphe niveau par niveau à partir d'une source , à l'aide d'une file. Complexité .
BFS(G, s) :
enfiler s, marquer s comme visité, distance(s)=0
tant que la file n'est pas vide :
u = défiler()
pour chaque voisin v de u non visité :
marquer v, distance(v) = distance(u)+1, enfiler v
Propriété clé : dans un graphe non pondéré, le BFS calcule exactement les plus courts chemins (en nombre d'arêtes) depuis vers tous les autres sommets atteignables.
4. Algorithme de Dijkstra (plus courts chemins, poids positifs)
Pour un graphe pondéré par des poids strictement positifs, l'algorithme de Dijkstra calcule les plus courts chemins depuis une source vers tous les autres sommets, en utilisant une file de priorité (tas-min) sur les distances provisoires :
Dijkstra(G, s) :
dist(s) = 0, dist(v) = +infini pour v ≠ s
file de priorité Q = {tous les sommets, priorité = dist}
tant que Q n'est pas vide :
u = extraire le sommet de Q de plus petite distance
pour chaque voisin v de u (arête de poids w) :
si dist(u) + w < dist(v) :
dist(v) = dist(u) + w (relaxation)
mettre à jour la priorité de v dans Q
Complexité : avec une implémentation par tas binaire (chaque extraction et chaque mise à jour de priorité coûte , et il y a relaxations au total).
Exemple résolu. Graphe orienté : (poids ), (poids ), (poids ), (poids ), (poids ). Depuis : . On extrait , on relâche () et (). On extrait (distance minimale ), on relâche via : , donc ; on relâche via : . On extrait (distance ), on relâche via : , donc . Résultat final : .
5. Pourquoi Dijkstra échoue avec des poids négatifs
Dijkstra suppose qu'une fois un sommet extrait de la file (sa distance finalisée), aucune amélioration future n'est possible — ce qui n'est vrai que si tous les poids restants sont positifs (toute relaxation ultérieure ne peut qu'augmenter une distance). Avec des poids négatifs, un chemin découvert plus tard pourrait être plus court, invalidant cette hypothèse. Pour des graphes avec poids négatifs (sans cycle de poids négatif), on utilise l'algorithme de Bellman-Ford (, plus lent mais correct dans ce cas).
6. Algorithme de Floyd-Warshall (tous les plus courts chemins)
Pour calculer les plus courts chemins entre toutes les paires de sommets, l'algorithme de Floyd-Warshall utilise une programmation dynamique en :
où est la plus courte distance de à en n'utilisant que les sommets intermédiaires . C'est avantageux par rapport à exécutions de Dijkstra () lorsque le graphe est dense ( proche de ).
7. Récapitulatif
| Algorithme | Problème résolu | Complexité |
| DFS / BFS | parcours, plus courts chemins (non pondéré) | |
| Dijkstra | plus courts chemins depuis une source (poids ) | |
| Bellman-Ford | plus courts chemins depuis une source (poids quelconques, sans cycle négatif) | |
| Floyd-Warshall | plus courts chemins entre toutes les paires |
Exercices
Quelle structure de données utilise naturellement le parcours en largeur (BFS) ?
Vrai ou faux : dans un graphe non pondéré, le BFS depuis une source calcule les plus courts chemins (en nombre d'arêtes) vers tous les sommets atteignables.
Quelle structure de données est utilisée par l'algorithme de Dijkstra pour sélectionner efficacement le prochain sommet à traiter ?
Vrai ou faux : l'algorithme de Dijkstra fonctionne correctement même si certaines arêtes ont un poids négatif.
Quelle est la complexité de l'algorithme de Floyd-Warshall pour calculer les plus courts chemins entre toutes les paires de sommets ?
Suivez votre progression
Connectez-vous pour sauvegarder votre avancement et gagner des XP.