Menu
Coddy logo textTech

Algorithme de Bellman-Ford

Dernière mise à jour

Bellman-Ford trouve le plus court chemin d'un nœud source vers tous les autres nœuds et, contrairement à Dijkstra, il fonctionne même lorsque certains poids d'arête sont négatifs. Il procède par relâchement en force brute : il balaie de façon répétée chaque arête et, si passer par cette arête donne une distance plus courte, il met à jour la distance du nœud cible. Appuyez sur lecture ci-dessus pour voir les distances provisoires diminuer passe après passe.

Après V - 1 passes sur toutes les arêtes, chaque plus court chemin (qui peut avoir au plus V - 1 arêtes) a été trouvé. Cela le rend O(V · E) - plus lent que Dijkstra, mais il gère les poids négatifs et peut détecter un cycle de poids négatif (si une V-ième passe relâche encore une arête, aucun plus court chemin n'existe).

Complexité en temps et en espace

MesureComplexitéNotes
TempsO(V · E)V − 1 passes sur toutes les E arêtes
EspaceO(V)Une distance par nœud
Poids négatifsPris en chargeSon avantage clé sur Dijkstra
Cycles négatifsDétectablesUne V-ième passe qui relâche en signale un

Étape par étape

ÉtapeCe qui se passe
1Fixez la distance de la source à 0 et toutes les autres à l'infini.
2Répétez l'étape suivante V − 1 fois.
3Pour chaque arête (u → v, w), vérifiez si dist[u] + w < dist[v].
4Si oui, relâchez-la : posez dist[v] = dist[u] + w.
5Arrêtez plus tôt si une passe complète ne change rien.

Exemple résolu

Source S sur 4 nœuds S, A, B, C avec les arêtes S→A (4), S→B (5), A→C (3), B→A (-3), relâchées dans cet ordre. Les distances commencent à S=0 et tout le reste à :

PasseDistances [S, A, B, C]Action
Init[0, ∞, ∞, ∞]La distance de la source est 0, toutes les autres l'infini.
1[0, 2, 5, 7]Relâche S→A à 4, S→B à 5, A→C à 7, puis B→A abaisse A à 5 + (-3) = 2.
2[0, 2, 5, 5]A→C améliore désormais C à 2 + 3 = 5 ; aucune autre arête ne se relâche.
3[0, 2, 5, 5]Aucune arête ne se relâche, donc les distances sont définitives : A coûte 2 via S→B→A.

Quand utiliser Bellman-Ford

À utiliser quandÀ éviter quand
Les poids d'arête peuvent être négatifs.Tous les poids sont non négatifs (Dijkstra est plus rapide).
Vous devez détecter des cycles de poids négatif.Le graphe est énorme et dense - O(V · E) est trop lent.
Le graphe est petit ou creux.Vous n'avez besoin que d'une requête source-cible sur un grand graphe.
Vous voulez une base simple et facile à implémenter.Les poids sont non négatifs et la latence compte.

Code de Bellman-Ford Algorithm

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

Code de Bellman-Ford Algorithm en Python

Python
1def bellman_ford(vertices, edges, start):2    dist = {v: float("inf") for v in vertices}3    dist[start] = 04    # Relax every edge V-1 times5    for _ in range(len(vertices) - 1):6        for u, v, w in edges:7            if dist[u] + w < dist[v]:8                dist[v] = dist[u] + w9    # One more pass: any improvement means a negative cycle10    for u, v, w in edges:11        if dist[u] + w < dist[v]:12            raise ValueError("Graph contains a negative-weight cycle")13    return dist14
15
16vertices = ["A", "B", "C", "D", "E"]17edges = [18    ("A", "B", 6), ("A", "C", 7), ("B", "D", 5), ("B", "E", -4),19    ("C", "D", -3), ("D", "B", -2), ("E", "D", 7),20]21
22for node, d in bellman_ford(vertices, edges, "A").items():23    print(f"A -> {node}: {d}")
Exécutez ce code dans le Playground Python

FAQ Bellman-Ford

Quelle est la complexité temporelle de Bellman-Ford ?
Bellman-Ford s'exécute en temps O(V · E) : il fait V - 1 passes, et chaque passe relâche les E arêtes. C'est plus lent que le O((V + E) log V) de Dijkstra, ce qui est le prix de la prise en charge des poids d'arête négatifs.
Quand utiliser Bellman-Ford plutôt que Dijkstra ?
Utilisez Bellman-Ford lorsque le graphe peut avoir des poids d'arête négatifs, ou lorsque vous devez détecter des cycles de poids négatif. Dijkstra est plus rapide mais n'est correct qu'avec des poids non négatifs. Un usage réel courant est la détection d'arbitrage de change, où les cycles négatifs comptent.
Comment Bellman-Ford détecte-t-il un cycle négatif ?
Après les V - 1 passes de relâchement, tous les plus courts chemins sont finalisés s'il n'existe aucun cycle négatif. Si une passe de plus peut encore relâcher une arête, alors un cycle de poids négatif est atteignable, et les plus courts chemins sont indéfinis (vous pourriez boucler à l'infini pour réduire le coût).
Quelle est la différence entre Bellman-Ford et Floyd-Warshall ?
Bellman-Ford calcule les plus courts chemins depuis une source unique en O(V · E), tandis que Floyd-Warshall calcule les plus courts chemins entre toutes les paires en O(V³). Sur un graphe dense, exécuter Bellman-Ford depuis chaque source coûte O(V² · E), donc Floyd-Warshall est généralement le meilleur choix quand vous avez besoin de toutes les paires. Les deux gèrent les arêtes négatives et peuvent signaler les cycles négatifs.
Pourquoi Bellman-Ford a-t-il besoin d'exactement V - 1 passes ?
Tout plus court chemin dans un graphe sans cycle négatif utilise au plus V - 1 arêtes, car un chemin visitant plus de V nœuds doit en répéter un. Chaque passe garantit qu'au moins une arête de plus de chaque plus court chemin est relâchée correctement, donc V - 1 passes suffisent à les fixer toutes. Une idée fausse courante est que plus de passes améliorent le résultat - elles ne le font jamais, sauf s'il existe un cycle négatif.
Bellman-Ford peut-il s'arrêter plus tôt ?
Oui. Si une passe complète sur toutes les arêtes ne relâche rien, toutes les distances sont déjà optimales et vous pouvez vous arrêter avant d'atteindre les V - 1 passes. Cette optimisation de sortie anticipée le rend souvent bien plus rapide sur les graphes qui convergent vite, même si la borne du pire cas reste O(V · E).
Coddy programming languages illustration

Maîtrisez les algorithmes avec Coddy

COMMENCER