Menu
Coddy logo textTech

Bellman-Ford Algoritması

Son güncelleme

Bellman-Ford, bir kaynak düğümden diğer tüm düğümlere en kısa yolu bulur ve Dijkstra'nın aksine bazı kenar ağırlıkları negatif olsa bile çalışır. Kaba kuvvet gevşetmesiyle çalışır: her kenarı tekrar tekrar tarar ve o kenardan geçmek daha kısa bir mesafe veriyorsa hedef düğümün mesafesini günceller. Geçici mesafelerin geçiş geçiş düştüğünü görmek için yukarıdan oynat'a basın.

Tüm kenarlar üzerinde V - 1 geçişten sonra, her en kısa yol (en fazla V - 1 kenar içerebilir) bulunmuş olur. Bu onu O(V · E) yapar - Dijkstra'dan daha yavaş, ancak negatif ağırlıkları işler ve negatif ağırlıklı bir döngüyü tespit edebilir (bir V. geçiş hâlâ bir kenarı gevşetiyorsa, en kısa yol yoktur).

Zaman ve alan karmaşıklığı

ÖlçütKarmaşıklıkNotlar
ZamanO(V · E)Tüm E kenarı üzerinde V − 1 geçiş
AlanO(V)Her düğüm için bir mesafe
Negatif ağırlıklarDestekleniyorDijkstra'ya karşı temel avantajı
Negatif döngülerTespit edilebilirGevşeten bir V. geçiş birini işaret eder

Adım adım

AdımNe olur
1Kaynak mesafesini 0, diğerlerinin tümünü sonsuz olarak ayarlayın.
2Sonraki adımı V − 1 kez tekrarlayın.
3Her kenar (u → v, w) için dist[u] + w < dist[v] olup olmadığını kontrol edin.
4Öyleyse gevşetin: dist[v] = dist[u] + w olarak ayarlayın.
5Tam bir geçiş hiçbir değişiklik yapmazsa erken durun.

Çözümlü örnek

4 düğümlü S, A, B, C üzerinde kaynak S, kenarlar S→A (4), S→B (5), A→C (3), B→A (-3), bu sırayla gevşetilir. Mesafeler S=0 ve diğer her şey olarak başlar:

GeçişMesafeler [S, A, B, C]Eylem
Init[0, ∞, ∞, ∞]Kaynak mesafesi 0, diğerlerinin tümü sonsuz.
1[0, 2, 5, 7]S→A 4'e, S→B 5'e, A→C 7'ye gevşer, ardından B→A A'yı 5 + (-3) = 2 değerine düşürür.
2[0, 2, 5, 5]A→C artık C'yi 2 + 3 = 5 değerine iyileştirir; başka hiçbir kenar gevşemez.
3[0, 2, 5, 5]Hiçbir kenar gevşemez, bu yüzden mesafeler kesindir: A, S→B→A üzerinden 2'ye mal olur.

Bellman-Ford ne zaman kullanılır

Şu durumda kullanınŞu durumda kaçının
Kenar ağırlıkları negatif olabilir.Tüm ağırlıklar negatif değil (Dijkstra daha hızlı).
Negatif ağırlıklı döngüleri tespit etmeniz gerekir.Graf çok büyük ve yoğun - O(V · E) çok yavaş.
Graf küçük veya seyrek.Büyük bir grafta yalnızca tek bir kaynak-hedef sorgusuna ihtiyacınız var.
Basit, uygulanması kolay bir temel gerekiyor.Ağırlıklar negatif değil ve gecikme önemli.

Bellman-Ford Algorithm kodu

Python, JavaScript, Java, C++, C dillerinde temiz ve çalıştırılabilir bir Bellman-Ford Algorithm uygulaması. Bir dil seçin, kodu kopyalayın veya Coddy Playground'da hazır yüklenmiş olarak açın.

Python ile Bellman-Ford Algorithm kodu

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}")
Bu kodu Python Playground'da çalıştır

Bellman-Ford SSS

Bellman-Ford'un zaman karmaşıklığı nedir?
Bellman-Ford O(V · E) sürede çalışır: V - 1 geçiş yapar ve her geçiş tüm E kenarını gevşetir. Bu, Dijkstra'nın O((V + E) log V) değerinden daha yavaştır; bu, negatif kenar ağırlıklarını desteklemenin bedelidir.
Dijkstra yerine Bellman-Ford'u ne zaman kullanmalıyım?
Graf negatif kenar ağırlıklarına sahip olabildiğinde veya negatif ağırlıklı döngüleri tespit etmeniz gerektiğinde Bellman-Ford kullanın. Dijkstra daha hızlıdır ancak yalnızca negatif olmayan ağırlıklarla doğrudur. Yaygın gerçek bir kullanım, negatif döngülerin önemli olduğu döviz arbitrajı tespitidir.
Bellman-Ford negatif bir döngüyü nasıl tespit eder?
V - 1 gevşetme geçişinden sonra, negatif döngü yoksa tüm en kısa yollar kesinleşir. Bir geçiş daha hâlâ bir kenarı gevşetebiliyorsa, ulaşılabilir negatif ağırlıklı bir döngü vardır ve en kısa yollar tanımsızdır (maliyeti düşürmek için sonsuza dek döngü kurabilirsiniz).
Bellman-Ford ile Floyd-Warshall arasındaki fark nedir?
Bellman-Ford, tek bir kaynaktan en kısa yolları O(V · E) sürede hesaplarken, Floyd-Warshall tüm çiftler arası en kısa yolları O(V³) sürede hesaplar. Yoğun bir grafta Bellman-Ford'u her kaynaktan çalıştırmak O(V² · E) maliyetlidir, bu yüzden tüm çiftlere ihtiyacınız olduğunda genellikle Floyd-Warshall daha iyi bir seçimdir. İkisi de negatif kenarları işler ve negatif döngüleri işaretleyebilir.
Bellman-Ford neden tam olarak V - 1 geçişe ihtiyaç duyar?
Negatif döngüsü olmayan bir graftaki herhangi bir en kısa yol en fazla V - 1 kenar kullanır, çünkü V'den fazla düğümü ziyaret eden bir yol birini tekrar etmek zorundadır. Her geçiş, her en kısa yolun en az bir kenarının daha doğru şekilde gevşetildiğini garanti eder, bu yüzden V - 1 geçiş hepsini oturtmaya yeter. Yaygın bir yanılgı, daha fazla geçişin sonucu iyileştirdiğidir - negatif bir döngü olmadıkça bunu asla yapmazlar.
Bellman-Ford erken durabilir mi?
Evet. Tüm kenarlar üzerindeki tam bir geçiş hiçbir şeyi gevşetmezse, tüm mesafeler zaten optimaldir ve V - 1 geçişe ulaşmadan durabilirsiniz. Bu erken çıkış optimizasyonu, hızlı yakınsayan graflarda onu genellikle çok daha hızlı yapar, ancak en kötü durum sınırı O(V · E) olarak kalır.
Coddy programming languages illustration

Coddy ile algoritmalarda ustalaş

BAŞLA