Bölüm 4.2: En Kısa Yol Algoritmaları

Algoritmalar
GevşetmeDijkstraBellman-FordNegatif döngü Floyd-WarshallA* aramaBFS ile ağırlıksız yolKarşılaştırma
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Kavramlar

Tek kaynaklı, tüm çiftler ve tek çift en kısa yol problemlerini ayırt etmek; gevşetme (relaxation) işlemini ve önceki (π) dizisini açıklamak.

Dijkstra ve Bellman-Ford

İki algoritmayı bir örnek çizge üzerinde adım adım çalıştırmak, uzaklık ve π tablolarını doldurmak, Java kodunu izlemek.

Negatif kenar ve döngü

Dijkstra'nın negatif kenarda neden yanıldığını göstermek; Bellman-Ford ve Floyd-Warshall ile negatif döngüyü tespit etmek.

Floyd-Warshall ve A*

Tüm çiftler için D ve Π matrislerini k = 1…n güncellemek; A*'ın f = g + h ile hedefe yönelen aramasını uygulamak ve algoritmaları karşılaştırmak.

Giriş

Yol Ağı Bir Çizgedir

  • Kavşaklar düğüm (vertex), yollar kenar (edge), yol uzunlukları ya da süreleri ağırlık (weight) olur.
  • Bir yolun uzunluğu = üzerindeki kenar ağırlıklarının toplamı.
  • En kısa yol (shortest path): iki düğüm arasındaki toplam ağırlığı en küçük yol; uzunluğu δ(s, v) ile gösterilir.
  • Örnek: Ev → Okul için Ev–1–2–4–Okul = 4 + 2 + 3 + 3 = 12; daha az kenarlı Ev–1–4–Okul ise 13 eder.
432632723Ev12Mkt3Göl4Okul
Kenar sayısı en az olan yol, ağırlıklı çizgede en kısa yol olmayabilir. Navigasyon, ağ yönlendirme (OSPF, RIP), oyunlarda yol bulma ve lojistik bu problemi çözer.

Giriş

En Kısa Yol Problem Türleri

Tek kaynaklı(single-source) s'den tüm düğümlere. Dijkstra, Bellman-Ford, BFS.
Tüm çiftler(all-pairs) her (u, v) çifti; sonuç n × n matris. Floyd-Warshall.
Tek çift(single-pair) yalnızca s → t; hedefe yönelen arama. A*.
AlgoritmaNe bulur?Kısıt / not
Dijkstrakaynaktan tüm düğümlerekenar ağırlıkları negatif olmamalı
Bellman-Fordkaynaktan tüm düğümlerenegatif kenarda çalışır, negatif döngüyü bulur; Dijkstra'dan yavaş
Floyd-Warshalltüm çiftler arasınegatif kenarda çalışır; negatif döngüyü köşegenden tespit eder
A*başlangıçtan hedefesezgisel (heuristic) tahminle aramayı hızlandırır
BFSkaynaktan tüm düğümlereyalnızca ağırlıksız (ya da eşit ağırlıklı) çizgeler

Giriş

Temel İşlem: Gevşetme (Relaxation)

Her düğüm için iki bilgi tutulur:

  • d[v]: şimdiye kadar bulunan en kısa yol tahmini (başta ∞, kaynakta 0)
  • π[v]: bu yolda v'den önceki düğüm (önceki, predecessor)
RELAX(u, v, w):
  eğer d[u] + w(u, v) < d[v]:
    d[v] = d[u] + w(u, v)
    π[v] = u
3suv059 → 8…

d[u] + w = 5 + 3 = 8 < 9 → d[v] = 8, π[v] = u

Bu bölümdeki tüm algoritmalar gevşetmeyi kullanır; fark, kenarları hangi sırayla ve kaç kez gevşettikleridir. d[v] yalnızca azalabilir ve hiçbir zaman gerçek δ(s, v)'nin altına inmez.

Giriş

En Kısa Yolların Özellikleri

Optimal alt yapı

En kısa yolun her alt yolu da en kısa yoldur. s ⇝ u ⇝ v en kısaysa s ⇝ u parçası da en kısadır. Dinamik programlama ve açgözlü yaklaşım buna dayanır.

Üçgen eşitsizliği

Her (u, v) kenarı için δ(s, v) ≤ δ(s, u) + w(u, v). Gevşetme bu eşitsizliği bozan kenarları düzeltir.

Negatif döngü

Toplam ağırlığı negatif olan bir döngü kaynaktan ulaşılabiliyorsa, döngüde dolaştıkça yol kısalır: en kısa yol tanımsızdır (−∞).

Basit yol

Negatif döngü yoksa en kısa yol döngü içermez; en fazla V − 1 kenarlıdır. Bellman-Ford'un V − 1 turu buradan gelir.

Yolu geri kurmak için π dizisi kullanılır: hedeften başlayıp π[v] ile kaynağa kadar geri gidilir; elde edilen düğümler ters sırada yazılır. Tüm π kenarları birlikte bir en kısa yol ağacı oluşturur.

Dijkstra

Dijkstra Algoritması

  • Kaynak düğümden diğer tüm düğümlere olan en kısa yolları bulur (tek kaynaklı).
  • 1956'da Edsger W. Dijkstra tarafından geliştirildi, 1959'da yayımlandı.
  • Yalnızca negatif olmayan ağırlıklı kenarlardan oluşan çizgelerde doğru çalışır.
  • Açgözlü (greedy): her adımda, henüz kesinleşmemiş düğümler arasından d değeri en küçük olanı seçer ve kesinleştirir.
  • Seçilen düğümün komşuları gevşetilir.
Sezgi: su dalgasıKaynağa bir taş atıldığını düşünün. Dalga, düğümlere uzaklık sırasıyla ulaşır: önce en yakın düğüm, sonra bir sonraki… Dijkstra düğümleri tam da bu sırayla kesinleştirir. Kesinleşen düğümlerin kümesine S denir.

Dijkstra

Dijkstra: Algoritma Adımları

Adım 1: Başlangıç düğümü seçilir, uzaklığı 0 atanır; diğer tüm düğümlerin uzaklığı ∞ olur.

İlklendirme: d[s] = 0, d[v] = ∞, π[v] = tanımsız, S = ∅.

Adım 2: Seçilen düğümden başlayarak, henüz işlenmemiş komşulara olan uzaklıklar hesaplanır.

Komşu v için aday uzaklık: d[u] + w(u, v).

Adım 3: Daha kısa bir yol bulunursa komşunun uzaklığı güncellenir (gevşetme).

d[u] + w(u, v) < d[v] ise d[v] ve π[v] değişir.

Adım 4: İşlenen düğüm işaretlenir (S'ye eklenir) ve uzaklığı en küçük işaretsiz düğüm seçilir.

Seçim, dizi ya da öncelik kuyruğu (priority queue) ile yapılır.

Adım 5: Tüm düğümler işlenene kadar Adım 2–4 tekrarlanır.

Ulaşılamayan düğümlerin uzaklığı ∞ olarak kalır.

Dijkstra

Dijkstra Örnek 1: Yönsüz Çizge, Kaynak 1

79141015112691234560∞∞∞∞∞
düğümdπ
10–
2∞–
3∞–
4∞–
5∞–
6∞–

İlklendirme: kaynak 1, d[1] = 0, diğerleri ∞. Hiçbir düğüm kesinleşmedi.

79141015112691234560∞∞∞∞∞
düğümdπ
10–
2∞–
3∞–
4∞–
5∞–
6∞–

Kesinleşmemişler içinde en küçük d: 1 (d = 0) seçilir ve kesinleşir.

791410151126912345607∞∞∞∞
düğümdπ
10–
271
3∞–
4∞–
5∞–
6∞–

Kenar (1, 2): d[1] + 7 = 7 < ∞ → d[2] = 7, π[2] = 1.

7914101511269123456079∞∞∞
düğümdπ
10–
271
391
4∞–
5∞–
6∞–

Kenar (1, 3): d[1] + 9 = 9 < ∞ → d[3] = 9, π[3] = 1.

7914101511269123456079∞∞14
düğümdπ
10–
271
391
4∞–
5∞–
6141

Kenar (1, 6): d[1] + 14 = 14 < ∞ → d[6] = 14, π[6] = 1.

7914101511269123456079∞∞14
düğümdπ
10–
271
391
4∞–
5∞–
6141

Kesinleşmemişler içinde en küçük d: 2 (d = 7) seçilir ve kesinleşir. Kesinleşmiş komşular (1) atlanır.

7914101511269123456079∞∞14
düğümdπ
10–
271
391
4∞–
5∞–
6141

Kenar (2, 3): d[2] + 10 = 17 ≥ 9 → değişiklik yok.

791410151126912345607922∞14
düğümdπ
10–
271
391
4222
5∞–
6141

Kenar (2, 4): d[2] + 15 = 22 < ∞ → d[4] = 22, π[4] = 2.

791410151126912345607922∞14
düğümdπ
10–
271
391
4222
5∞–
6141

Kesinleşmemişler içinde en küçük d: 3 (d = 9) seçilir ve kesinleşir. Kesinleşmiş komşular (1, 2) atlanır.

791410151126912345607920∞14
düğümdπ
10–
271
391
4203
5∞–
6141

Kenar (3, 4): d[3] + 11 = 20 < 22 → d[4] = 20, π[4] = 3.

791410151126912345607920∞11
düğümdπ
10–
271
391
4203
5∞–
6113

Kenar (3, 6): d[3] + 2 = 11 < 14 → d[6] = 11, π[6] = 3.

791410151126912345607920∞11
düğümdπ
10–
271
391
4203
5∞–
6113

Kesinleşmemişler içinde en küçük d: 6 (d = 11) seçilir ve kesinleşir. Kesinleşmiş komşular (1, 3) atlanır.

7914101511269123456079202011
düğümdπ
10–
271
391
4203
5206
6113

Kenar (6, 5): d[6] + 9 = 20 < ∞ → d[5] = 20, π[5] = 6.

7914101511269123456079202011
düğümdπ
10–
271
391
4203
5206
6113

Kesinleşmemişler içinde en küçük d: 4 (d = 20) seçilir ve kesinleşir. (4 ve 5 eşit: 20; küçük numaralı 4 alındı.) Kesinleşmiş komşular (2, 3) atlanır.

7914101511269123456079202011
düğümdπ
10–
271
391
4203
5206
6113

Kenar (4, 5): d[4] + 6 = 26 ≥ 20 → değişiklik yok.

7914101511269123456079202011
düğümdπ
10–
271
391
4203
5206
6113

Kesinleşmemişler içinde en küçük d: 5 (d = 20) seçilir ve kesinleşir. Kesinleşmiş komşular (4, 6) atlanır.

7914101511269123456079202011
düğümdπ
10–
271
391
4203
5206
6113

Bitti: 1'den uzaklıklar 2:7, 3:9, 6:11, 4:20, 5:20. Yeşil kenarlar en kısa yol ağacını oluşturur (ör. 1 → 3 → 6 → 5).

Dijkstra

Dijkstra Örnek 2: Yönlü Çizge, Q ve S Kümeleri

6332114212345∞∞∞∞0

Q

duπ
05/
∞1/
∞2/
∞3/
∞4/

S

udπ

İlklendirme: kaynak 5'in uzaklığı 0, diğerleri ∞. Tüm düğümler Q'da, S = ∅.

6332114212345∞4∞20

Q

duπ
245
425
∞1/
∞3/

S

udπ
50/

Adım 1: Q'dan 5 alınır, d = 0 ile S'ye konur. Gevşetme: (5,2): ∞ → 4; (5,4): ∞ → 2.

6332114212345∞3320

Q

duπ
324
334
∞1/

S

udπ
50/
425

Adım 2: Q'dan 4 alınır, d = 2 ile S'ye konur. Gevşetme: (4,2): 4 → 3; (4,3): ∞ → 3.

633211421234563320

Q

duπ
334
612

S

udπ
50/
425
234

Adım 3: Q'dan 2 alınır, d = 3 ile S'ye konur. Gevşetme: (2,1): ∞ → 6. (2 ve 3 eşit: 3; küçük numaralı 2 alındı.)

633211421234563320

Q

duπ
612

S

udπ
50/
425
234
334

Adım 4: Q'dan 3 alınır, d = 3 ile S'ye konur. Gevşetme: (3,4): 4 zaten S'de. Daha kısa yol çıkmaz (gevşetme yok).

633211421234563320

Q

duπ

S

udπ
50/
425
234
334
162

Adım 5: Q'dan 1 alınır, d = 6 ile S'ye konur. Gevşetme: (1,3): 3 zaten S'de; (1,4): 4 zaten S'de. Daha kısa yol çıkmaz (gevşetme yok).

633211421234563320
12345
d63320
π2445/

Son durum: 5'ten en kısa yollar. Yalnızca π kenarları (yeşil) kalır: 5→4→2→1 (6), 5→4→3 (3).

Dijkstra

Dijkstra: Sözde Kod

DIJKSTRA(G, kaynak):
  mesafeler = [ ]; ziyaretEdildi = [ ]
  öncelikKuyruğu = { }
  her bir v için V içinde:
    mesafeler[v] = sonsuz
    ziyaretEdildi[v] = 0
  mesafeler[kaynak] = 0
  öncelikKuyruğu.ekle(kaynak, 0)
  döngü öncelikKuyruğu boş değil iken:
    u = öncelikKuyruğu.çıkar()   // en küçük mesafe
    eğer ziyaretEdildi[u] == 0:
      ziyaretEdildi[u] = 1
      her bir (u, v) için G[u] içinde:
        eğer mesafeler[u] + ağırlık(u, v) < mesafeler[v]:
          mesafeler[v] = mesafeler[u] + ağırlık(u, v)
          öncelikKuyruğu.ekle(v, mesafeler[v])
  döndür mesafeler
Tembel silme: bir düğüm kuyruğa birden çok kez girebilir; eski kayıt çıkarıldığında ziyaretEdildi kontrolü onu atlar. Yol için gevşetmede önceki[v] = u da saklanır.

Dijkstra

Dijkstra (Öncelik Kuyruğu): Kodu Adım Adım İzle

void dijkstra(int kaynak) {
  int[] uzaklik = new int[V + 1];
  int[] onceki = new int[V + 1];
  boolean[] ziyaret = new boolean[V + 1];
  Arrays.fill(uzaklik, SONSUZ);
  uzaklik[kaynak] = 0;
  PriorityQueue<int[]> kuyruk =
    new PriorityQueue<>((a, b) -> a[1] - b[1]);
  kuyruk.add(new int[] { kaynak, 0 });
  while (!kuyruk.isEmpty()) {
    int u = kuyruk.poll()[0];
    if (ziyaret[u]) continue; // eski kayıt
    ziyaret[u] = true;
    for (Kenar k : komsu.get(u)) {
      int v = k.hedef, w = k.agirlik;
      if (!ziyaret[v]
          && uzaklik[u] + w < uzaklik[v]) {
        uzaklik[v] = uzaklik[u] + w;
        onceki[v] = u;
        kuyruk.add(new int[] { v, uzaklik[v] });
      }
    }
  }
}
6332114212345∞∞∞∞0

Diziler kurulur (düğümler 1..5, indis 0 kullanılmaz); uzaklik[5] = 0 ve (5, 0) kuyruğa eklenir.

6332114212345∞∞∞∞0

Kuyruktan en küçük uzaklıklı kayıt (5, 0) alınır: u = 5.

6332114212345∞∞∞∞0

5 kesinleşir: ziyaret[5] = true.

6332114212345∞∞∞∞0

Kenar 5→2 (w = 4): 0 + 4 < ∞ → koşul doğru.

6332114212345∞4∞∞0

uzaklik[2] = 4, onceki[2] = 5; (2, 4) kuyruğa eklenir.

6332114212345∞4∞∞0

Kenar 5→4 (w = 2): 0 + 2 < ∞ → koşul doğru.

6332114212345∞4∞20

uzaklik[4] = 2, onceki[4] = 5; (4, 2) kuyruğa eklenir.

6332114212345∞4∞20

Kuyruktan en küçük uzaklıklı kayıt (4, 2) alınır: u = 4.

6332114212345∞4∞20

4 kesinleşir: ziyaret[4] = true.

6332114212345∞4∞20

Kenar 4→2 (w = 1): 2 + 1 < 4 → koşul doğru.

6332114212345∞3∞20

uzaklik[2] = 3, onceki[2] = 4; (2, 3) kuyruğa eklenir.

6332114212345∞3∞20

Kenar 4→3 (w = 1): 2 + 1 < ∞ → koşul doğru.

6332114212345∞3320

uzaklik[3] = 3, onceki[3] = 4; (3, 3) kuyruğa eklenir.

6332114212345∞3320

Kuyruktan en küçük uzaklıklı kayıt (2, 3) alınır: u = 2.

6332114212345∞3320

2 kesinleşir: ziyaret[2] = true.

6332114212345∞3320

Kenar 2→1 (w = 3): 3 + 3 < ∞ → koşul doğru.

633211421234563320

uzaklik[1] = 6, onceki[1] = 2; (1, 6) kuyruğa eklenir.

633211421234563320

Kuyruktan en küçük uzaklıklı kayıt (3, 3) alınır: u = 3.

633211421234563320

3 kesinleşir: ziyaret[3] = true.

633211421234563320

Kenar 3→4 (w = 2): ziyaret[4] = true → koşul yanlış.

633211421234563320

Kuyruktan en küçük uzaklıklı kayıt (2, 4) alınır: u = 2.

633211421234563320

ziyaret[2] zaten true: bu, 2'nin eski (2, 4) kaydı → continue ile atlanır (tembel silme).

633211421234563320

Kuyruktan en küçük uzaklıklı kayıt (1, 6) alınır: u = 1.

633211421234563320

1 kesinleşir: ziyaret[1] = true.

633211421234563320

Kenar 1→3 (w = 6): ziyaret[3] = true → koşul yanlış.

633211421234563320

Kenar 1→4 (w = 3): ziyaret[4] = true → koşul yanlış.

633211421234563320

Kuyruk boş: döngü biter. uzaklik = [6, 3, 3, 2, 0], onceki = [2, 4, 4, 5, –].

Dijkstra

Yolu Geri Kurma: π (önceki) Dizisi

Örnek 2'nin sonucu: π = [2, 4, 4, 5, /]. Hedef 1 için geriye doğru:

1 ← π[1] = 2 ← π[2] = 4 ← π[4] = 5 (kaynak)

Ters çevrilince yol: 5 → 4 → 2 → 1, uzunluk 2 + 1 + 3 = 6 = d[1].

void yolYaz(int[] onceki, int kaynak, int hedef) {
  Deque<Integer> yigin = new ArrayDeque<>();
  for (int v = hedef; v != kaynak; v = onceki[v])
    yigin.push(v);         // hedeften geriye
  yigin.push(kaynak);
  while (!yigin.isEmpty())
    System.out.print(yigin.pop() + " ");
}
633211421234563320

Yığın (stack) geriye doğru toplanan düğümleri doğru sıraya çevirir.

Dijkstra

Dijkstra: Algoritma Karmaşıklığı

Maliyet, en küçük uzaklıklı düğümü seçme işleminin nasıl yapıldığına bağlıdır:

Seçim yapısıSeçimGevşetmeToplamUygun çizge
Dizi (doğrusal tarama)V × O(V)E × O(1)O(V²)yoğun (E ≈ V²)
İkili yığın (öncelik kuyruğu)O(log V)O(log V)O((V + E) log V)seyrek (E ≪ V²)
Fibonacci yığınıO(log V) amortizeO(1) amortizeO(E + V log V)kuramsal en iyi
Sayısal örnekV = 10⁴, E = 5·10⁴ (yol ağı): dizi ≈ 10⁸ işlem, yığın ≈ 6·10⁴ · 14 ≈ 8,4·10⁵ işlem.
Bellekd, π ve ziyaret dizileri O(V); tembel silmeli kuyrukta en fazla E kayıt → O(V + E).

Dijkstra

Dijkstra Neden Negatif Kenarda Yanılır?

  • Doğruluk kanıtı şuna dayanır: kesinleşen u için, S dışından geçen her yol en az d[u] uzunluğundadır; çünkü kenarlar negatif değildir ve yol yalnızca uzayabilir.
  • Negatif kenar bu varsayımı bozar: sonradan işlenen bir düğüm, kesinleşmiş bir düğüme daha kısa yol açabilir.
  • Tüm ağırlıklara sabit eklemek de çözüm değildir: çok kenarlı yollar daha fazla ceza alır, en kısa yol değişir.
  • Negatif kenar varsa Bellman-Ford kullanılır.
23-2ABC023

A kesinleşir; gevşetme ile d[B] = 2, d[C] = 3.

23-2ABC023

En küçük d: B (2). Dijkstra B'yi kesinleştirir: “B'ye daha kısa yol olamaz” varsayımı.

23-2ABC02 ✗3

C işlenir: d[C] + (−2) = 1 < 2, ama B zaten S'de. Sonuç d[B] = 2 yanlış; gerçek δ(A, B) = 1 (A → C → B).

Bellman-Ford

Bellman-Ford Algoritması

  • Kaynak düğümden diğer tüm düğümlere olan en kısa yolları bulur (tek kaynaklı).
  • Richard Bellman (1958) ve Lester Ford Jr. (1956) adlarını taşır; E. F. Moore da 1959'da aynı yöntemi verdi.
  • Negatif ağırlıklı kenarları işleyebilir.
  • Kaynaktan ulaşılabilen negatif döngüleri tespit edebilir.
  • Dijkstra'dan yavaştır: O(V · E).
Algoritma ilkeleriHer düğüm için en kısa yol tahminlerini tutan bir dizi kullanır. Başta tüm tahminler ∞, kaynak 0'dır. Çizgedeki tüm kenarlar teker teker incelenir ve tahminler güncellenir; bu tarama V − 1 kez tekrarlanır. Düğüm seçimi yoktur, açgözlü değildir.

Bellman-Ford

Bellman-Ford: Algoritma Adımları

Adım 1: Başlangıç düğümüne uzaklık 0, diğer düğümlere ∞ atanır.

π[v] = tanımsız.

Adım 2: Kenarlar tek tek incelenir, düğümler arası uzaklıklar gevşetme ile güncellenir; bu tur V − 1 kez tekrarlanır.

Bir turda kenar sırası sabittir; sıra sonucu değil, kaç turda yakınsayacağını etkiler.

Adım 3: Bir düğümün uzaklığı güncellenirse, sonraki incelemelerde onun komşularının uzaklıkları da güncellenebilir.

İyileşme, yol boyunca her turda en az bir kenar ilerler.

Adım 4: Negatif döngü kontrolü için tüm kenarlar bir kez daha incelenir; hâlâ gevşeyen kenar varsa negatif döngü vardır.

Döngü yoksa V − 1 turdan sonra hiçbir kenar gevşemez.

Bellman-Ford

Neden V − 1 Tur? Karmaşıklık

  • Negatif döngü yoksa her en kısa yol en fazla V − 1 kenarlıdır.
  • Değişmez: i. turun sonunda, en fazla i kenarlı en kısa yolu olan her v için d[v] = δ(s, v).
  • Tur i'de yolun i. kenarı mutlaka gevşetilir; V − 1 tur tüm yolları tamamlar.
  • Her tur E kenarı inceler: toplam O(V · E) zaman, O(V) ek bellek.
ÇizgeZaman
Seyrek, E ≈ VO(V²)
Yoğun, E ≈ V²O(V³)
En iyi durum (erken durma)O(E)
Erken durma: bir turda hiçbir d değişmezse sonraki turlar da değiştirmez; döngüden çıkılabilir.

Bellman-Ford

Bellman-Ford Örnek 1: Kenar Kenar Gevşetme

93622122sv₁v₄v₂v₃0∞∞∞∞
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

İlklendirme: d[s] = 0, diğerleri ∞. Kenarlar her turda yukarıdaki sırayla incelenir.

93622122sv₁v₄v₂v₃09∞∞∞
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (s, v₁): 0 + 9 = 9 < ∞ → d[v₁] = 9.

93622122sv₁v₄v₂v₃093∞∞
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (s, v₂): 0 + 3 = 3 < ∞ → d[v₂] = 3.

93622122sv₁v₄v₂v₃093∞∞
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (v₁, v₂): 9 + 6 = 15 ≥ 3 → değişmez.

93622122sv₁v₄v₂v₃093∞11
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (v₁, v₄): 9 + 2 = 11 < ∞ → d[v₄] = 11.

93622122sv₁v₄v₂v₃053∞11
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (v₂, v₁): 3 + 2 = 5 < 9 → d[v₁] = 5.

93622122sv₁v₄v₂v₃053411
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (v₂, v₃): 3 + 1 = 4 < ∞ → d[v₃] = 4.

93622122sv₁v₄v₂v₃053411
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (v₃, v₂): 4 + 2 = 6 ≥ 3 → değişmez.

93622122sv₁v₄v₂v₃05346
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 1, kenar (v₃, v₄): 4 + 2 = 6 < 11 → d[v₄] = 6.

93622122sv₁v₄v₂v₃05346
(s,v₁) 9(s,v₂) 3(v₁,v₂) 6(v₁,v₄) 2(v₂,v₁) 2(v₂,v₃) 1(v₃,v₂) 2(v₃,v₄) 2

Tur 2: sekiz kenarın hiçbiri gevşemez → erken durma. Sonuç: v₁ = 5, v₂ = 3, v₃ = 4, v₄ = 6 (bu sırada tek tur yetti).

Bellman-Ford

Bellman-Ford Örnek 2: Negatif Kenarlar

3-1-2-214-4SABCDE0∞∞∞∞∞
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Negatif kenarlı çizge, kaynak S. Kenarlar her turda yukarıdaki sırayla incelenir (sondan başa: en kötü sıra).

3-1-2-214-4SABCDE03∞∞∞∞
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Tur 1: yalnızca (S,A): ∞ → 3. Diğer kenarların başı hâlâ ∞.

3-1-2-214-4SABCDE032∞∞∞
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Tur 2: yalnızca (A,B): ∞ → 2.

3-1-2-214-4SABCDE0320∞∞
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Tur 3: yalnızca (B,C): ∞ → 0.

3-1-2-214-4SABCDE0320-21
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Tur 4: yalnızca (C,D): ∞ → -2; (C,E): ∞ → 1.

3-1-2-214-4SABCDE0320-31
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Tur 5: yalnızca (E,D): -2 → -3. E üzerinden D'ye daha kısa yol: 1 + (−4) = −3.

3-1-2-214-4SABCDE0320-31
(E,D) -4(E,A) 4(C,D) -2(C,E) 1(B,C) -2(A,B) -1(S,A) 3

Denetim turu: hiçbir kenar gevşemez → negatif döngü yok (A→B→C→E→A = −1 −2 + 1 + 4 = +2). V − 1 = 5 turun hepsi gerekti.

Bellman-Ford

Bellman-Ford Örnek 3: Dijkstra Örnek 2'deki Çizge

6332114212345∞∞∞∞0
12345
d∞∞∞∞0
π/////
(1,3) 6(1,4) 3(2,1) 3(3,4) 2(4,2) 1(4,3) 1(5,2) 4(5,4) 2

İlklendirme: kaynak 5'in uzaklığı 0, diğerleri ∞. Kenar sırası: (1,3), (1,4), (2,1), (3,4), (4,2), (4,3), (5,2), (5,4).

6332114212345∞4∞20
12345
d∞4∞20
π/5/5/
(1,3) 6(1,4) 3(2,1) 3(3,4) 2(4,2) 1(4,3) 1(5,2) 4(5,4) 2

Tur 1: (5,2): ∞ → 4; (5,4): ∞ → 2.

633211421234573320
12345
d73320
π2445/
(1,3) 6(1,4) 3(2,1) 3(3,4) 2(4,2) 1(4,3) 1(5,2) 4(5,4) 2

Tur 2: (2,1): ∞ → 7; (4,2): 4 → 3; (4,3): ∞ → 3. (4,2) kenarı 2'ye daha kısa yol buldu.

633211421234563320
12345
d63320
π2445/
(1,3) 6(1,4) 3(2,1) 3(3,4) 2(4,2) 1(4,3) 1(5,2) 4(5,4) 2

Tur 3: (2,1): 7 → 6. 2 bir önceki turda iyileştiği için (2,1) yeniden gevşer.

633211421234563320
12345
d63320
π2445/
(1,3) 6(1,4) 3(2,1) 3(3,4) 2(4,2) 1(4,3) 1(5,2) 4(5,4) 2

Tur 4: daha kısa yol bulunamadı (hiçbir kenar gevşemez).

Bellman-Ford

Negatif Döngü Kontrolü (V. Tur)

Her kenar için son bir kez gevşetme denenir: d[v] > d[u] + w(u, v) olan bir kenar kalırsa negatif döngü vardır. Örnek 3'ün sonucunda:

kenard[v]d[u] + w(u, v)sonuç
(1, 3)d[3] = 3d[1] + w = 6 + 6 = 123 ≯ 12 ✓
(1, 4)d[4] = 2d[1] + w = 6 + 3 = 92 ≯ 9 ✓
(2, 1)d[1] = 6d[2] + w = 3 + 3 = 66 ≯ 6 ✓
(3, 4)d[4] = 2d[3] + w = 3 + 2 = 52 ≯ 5 ✓
(4, 2)d[2] = 3d[4] + w = 2 + 1 = 33 ≯ 3 ✓
(4, 3)d[3] = 3d[4] + w = 2 + 1 = 33 ≯ 3 ✓
(5, 2)d[2] = 3d[5] + w = 0 + 4 = 43 ≯ 4 ✓
(5, 4)d[4] = 2d[5] + w = 0 + 2 = 22 ≯ 2 ✓
Hiçbir kenar gevşemiyor → negatif döngü yok; d = [6, 3, 3, 2, 0] kesindir.

Bellman-Ford

Negatif Döngü Tespiti: Örnek

21-31SABC0-11-2

A → B → C → A döngüsü: 1 + (−3) + 1 = −1. Kenar sırası: (S,A), (A,B), (B,C), (C,A).

turSABC
10130
2002-1
30-11-2
  • V − 1 = 3 tur sonunda d = [0, −1, 1, −2]; döngüdeki değerler her turda 1 azalıyor.
  • Denetim: (A, B) için d[A] + 1 = 0 < d[B] = 1 → negatif döngü var.
  • Döngüdeki ve döngüden ulaşılan düğümlerin en kısa yolu −∞'dur (tanımsız).

Bellman-Ford

Bellman-Ford: Sözde Kod

BELLMAN_FORD(G, kaynak):
  mesafeler = [ ]
  her bir v için V içinde:
    mesafeler[v] = sonsuz
  mesafeler[kaynak] = 0
  döngü i = 1 den |V| - 1:
    her bir (u, v, ağırlık) için E içinde:
      eğer mesafeler[u] + ağırlık < mesafeler[v]:
        mesafeler[v] = mesafeler[u] + ağırlık
  her bir (u, v, ağırlık) için E içinde:
    eğer mesafeler[u] + ağırlık < mesafeler[v]:
      hata "Negatif ağırlıklı döngü var"
  döndür mesafeler
İki bölümDış döngü V − 1 tur; her turda tüm kenarlar. Ardından tek bir denetim turu.
Kenar listesiBellman-Ford düğüm seçmediği için çizgeyi bir kenar listesi E olarak tutmak yeterlidir.

Bellman-Ford

Bellman-Ford: Kodu Adım Adım İzle

void bellmanFord(int kaynak) {
  int[] uzaklik = new int[V];
  int[] onceki = new int[V];
  Arrays.fill(uzaklik, SONSUZ);
  uzaklik[kaynak] = 0;
  for (int i = 1; i < V; i++) {
    for (Kenar k : kenarlar) {
      int u = k.bas, v = k.son, w = k.agirlik;
      if (uzaklik[u] != SONSUZ
          && uzaklik[u] + w < uzaklik[v]) {
        uzaklik[v] = uzaklik[u] + w;
        onceki[v] = u;
      }
    }
  }
  for (Kenar k : kenarlar) { // denetim
    int u = k.bas, v = k.son, w = k.agirlik;
    if (uzaklik[u] != SONSUZ
        && uzaklik[u] + w < uzaklik[v])
      throw new IllegalStateException(
          "Negatif döngü");
  }
}
-245301230∞∞∞

Kaynak 0. uzaklik = [0, ∞, ∞, ∞]. Kenar listesi: (2,1,−2), (0,1,4), (0,2,5), (1,3,3).

-245301230∞∞∞

Tur 1, kenar (2,1): uzaklik[2] = ∞ → koşul yanlış, atlanır.

-245301230∞∞∞

Tur 1, kenar (0,1): 0 + (4) = 4 < ∞ → koşul doğru.

-2453012304∞∞

uzaklik[1] = 4, onceki[1] = 0.

-2453012304∞∞

Tur 1, kenar (0,2): 0 + (5) = 5 < ∞ → koşul doğru.

-24530123045∞

uzaklik[2] = 5, onceki[2] = 0.

-24530123045∞

Tur 1, kenar (1,3): 4 + (3) = 7 < ∞ → koşul doğru.

-245301230457

uzaklik[3] = 7, onceki[3] = 1. Tur 1 bitti: (2,1) kenarı 2 henüz ∞ iken incelendiği için boşa geçti.

-245301230457

Tur 2, kenar (2,1): 5 + (-2) = 3 < 4 → koşul doğru.

-245301230357

uzaklik[1] = 3, onceki[1] = 2.

-245301230357

Tur 2, kenar (0,1): 0 + (4) = 4 ≥ 3 → değişiklik yok.

-245301230357

Tur 2, kenar (0,2): 0 + (5) = 5 ≥ 5 → değişiklik yok.

-245301230357

Tur 2, kenar (1,3): 3 + (3) = 6 < 7 → koşul doğru.

-245301230356

uzaklik[3] = 6, onceki[3] = 1. Tur 2 bitti: negatif kenar 1'i 3'e, o da 3'ü 6'ya indirdi.

-245301230356

Tur 3, kenar (2,1): 5 + (-2) = 3 ≥ 3 → değişiklik yok.

-245301230356

Tur 3, kenar (0,1): 0 + (4) = 4 ≥ 3 → değişiklik yok.

-245301230356

Tur 3, kenar (0,2): 0 + (5) = 5 ≥ 5 → değişiklik yok.

-245301230356

Tur 3, kenar (1,3): 3 + (3) = 6 ≥ 6 → değişiklik yok.

-245301230356

Tur 3 hiçbir şeyi değiştirmedi. Denetim turu (satır 16–20): hiçbir kenar gevşemez, istisna fırlatılmaz. Sonuç [0, 3, 5, 6].

Floyd-Warshall

Floyd-Warshall Algoritması

  • Tüm düğüm çiftleri arasındaki en kısa yolları bulur (all-pairs).
  • Bernard Roy (1959), Stephen Warshall (1962, geçişli kapanış) ve Robert Floyd (1962, en kısa yol) tarafından birbirinden bağımsız verilmiştir.
  • Negatif ağırlıklı kenarlarla çalışır; negatif döngüyü tespit eder (o durumda en kısa yol tanımsızdır).
  • Dinamik programlama kullanır; sonuçları bir V × V matriste (D) tutar.
Tek kaynak mı, tüm çiftler mi?Bellman-Ford ve Dijkstra tek kaynaktan diğer düğümlere en kısa yolları bulur. Floyd-Warshall ise tüm çiftler arasındaki en kısa yolları tek seferde, üç iç içe döngüyle hesaplar. Kod çok kısadır; yoğun çizgelerde pratiktir.

Floyd-Warshall

Floyd-Warshall: Adımlar ve Yineleme Bağıntısı

  1. Adım 1: D matrisi kenar ağırlıklarıyla doldurulur: D[i][i] = 0; doğrudan kenar yoksa ∞.
  2. Adım 2: Ara düğüm k = 1, 2, …, n sırayla ele alınır; her (i, j) çifti için…
  3. Adım 3: k üzerinden geçen yolun uzunluğu D[i][k] + D[k][j] hesaplanır ve mevcut D[i][j] ile karşılaştırılır.
  4. Adım 4: Daha kısaysa yeni değer matrise yazılır (Π matrisi de güncellenir).
Alt problemD(k)[i][j]: ara düğümleri yalnızca {1, …, k} kümesinden seçilen en kısa i ⇝ j yolunun uzunluğu.
D(k)[i][j] = min( D(k−1)[i][j], D(k−1)[i][k] + D(k−1)[k][j] )
k ya yolda yoktur ya da yol k'den bir kez geçer. D(n) sonuçtur.

Floyd-Warshall

Floyd-Warshall: Karmaşıklık

  • Zaman Θ(V³): 3 iç içe for döngüsü, her biri V kez.
    • ilk (en dış) döngü tüm ara düğümleri (k) gezer,
    • ikinci döngü tüm kaynak düğümleri (i) gezer,
    • son döngü tüm hedef düğümleri (j) gezer.
  • Bellek Θ(V²): D yerinde (in-place) güncellenebilir; k. satır ve sütun k turunda değişmez.
Tüm çiftler içinZaman
Floyd-WarshallO(V³)
V × Dijkstra (dizi)O(V³)
V × Dijkstra (yığın)O(V(V + E) log V)
V × Bellman-FordO(V² E)
Döngü sırası önemlidir: k en dışta olmalıdır. k içeride olursa sonuç yanlış çıkar.

Floyd-Warshall

Floyd-Warshall Örneği: D ve Π Matrisleri

6332114212345

D(0)

12345
10∞63∞
230∞∞∞
3∞∞02∞
4∞110∞
5∞4∞20

Π(0)

12345
1//11/
22////
3///3/
4/44//
5/5/5/

k = 0 (ilklendirme): D kenar ağırlıklarıyla doldurulur, köşegen 0, kenar yoksa ∞. Π[i][j] = i (doğrudan kenar varsa), yoksa /.

6332114212345

D(1)

12345
10∞63∞
23096∞
3∞∞02∞
4∞110∞
5∞4∞20

Π(1)

12345
1//11/
22/11/
3///3/
4/44//
5/5/5/

k = 1: düğüm 1 üzerinden 2 ⇝ 3 (3 + 6 = 9) ve 2 ⇝ 4 (3 + 3 = 6) yolları bulundu.

6332114212345

D(2)

12345
10∞63∞
23096∞
3∞∞02∞
44110∞
5741320

Π(2)

12345
1//11/
22/11/
3///3/
4244//
52515/

k = 2: düğüm 2 üzerinden 4 ⇝ 1 (1 + 3 = 4), 5 ⇝ 1 (4 + 3 = 7) ve 5 ⇝ 3 (4 + 9 = 13) bulundu.

6332114212345

D(3)

12345
10∞63∞
23096∞
3∞∞02∞
44110∞
5741320

Π(3)

12345
1//11/
22/11/
3///3/
4244//
52515/

k = 3: düğüm 3 üzerinden kısa yol bulunamadı (3'ten yalnızca 4'e kenar var, hiçbir değer iyileşmez).

6332114212345

D(4)

12345
10443∞
23076∞
36302∞
44110∞
563320

Π(4)

12345
1/441/
22/41/
324/3/
4244//
52445/

k = 4: düğüm 4 üzerinden 1⇝2, 1⇝3, 2⇝3, 3⇝1, 3⇝2, 5⇝1, 5⇝2, 5⇝3 kısaldı (8 hücre). Ör. 5⇝3: 2 + 1 = 3 < 13.

6332114212345

D(5)

12345
10443∞
23076∞
36302∞
44110∞
563320

Π(5)

12345
1/441/
22/41/
324/3/
4244//
52445/

k = 5: düğüm 5 üzerinden kısa yol yok (5'e gelen kenar olmadığından D[i][5] = ∞). Son matrisler hazır.

Floyd-Warshall

Son Durum ve Yolun Okunması

D (uzaklıklar)

12345
10443∞
23076∞
36302∞
44110∞
563320

Π (önceki)

12345
1/441/
22/41/
324/3/
4244//
52445/
  • Π[i][j]: i'den j'ye en kısa yolda j'den önceki düğüm.
  • 5 ⇝ 1: Π[5][1] = 2, Π[5][2] = 4, Π[5][4] = 5 → 5 → 4 → 2 → 1, D[5][1] = 6.
  • 1 ⇝ 2: Π[1][2] = 4, Π[1][4] = 1 → 1 → 4 → 2, D[1][2] = 4.
  • 5. sütun ∞: 5'e hiçbir düğümden ulaşılamaz.
  • 5. satır, Dijkstra ve Bellman-Ford'un kaynak 5 için bulduğu [6, 3, 3, 2, 0] ile aynıdır.

Floyd-Warshall

Floyd-Warshall: Sözde Kod

1. İlklendirme

FLOYD_WARSHALL(G):
  mesafeler = [ ][ ]
  her bir u için V içinde:
    her bir v için V içinde:
      eğer u == v:
        mesafeler[u][v] = 0
      yoksa eğer (u, v) E içinde:
        mesafeler[u][v] = ağırlık(u, v)
      yoksa:
        mesafeler[u][v] = sonsuz

2. Üç iç içe döngü ve denetim (m = mesafeler)

  her bir k için V içinde:
    her bir i için V içinde:
      her bir j için V içinde:
        eğer m[i][k] + m[k][j] < m[i][j]:
          m[i][j] = m[i][k] + m[k][j]
  her bir i için V içinde:
    eğer mesafeler[i][i] < 0:
      hata "Negatif ağırlıklı döngü var"
  döndür mesafeler

Floyd-Warshall

Floyd-Warshall: Java

void floydWarshall(int[][] d) {  // V x V
  for (int k = 0; k < V; k++)       // ara
    for (int i = 0; i < V; i++)     // kaynak
      for (int j = 0; j < V; j++)   // hedef
        if (d[i][k] != SONSUZ
            && d[k][j] != SONSUZ
            && d[i][k] + d[k][j] < d[i][j]) {
          d[i][j] = d[i][k] + d[k][j];
          onceki[i][j] = onceki[k][j];
        }
  for (int i = 0; i < V; i++)
    if (d[i][i] < 0)
      throw new IllegalStateException(
          "Negatif döngü");
}
  • Matris yerinde güncellenir; ayrı D(k) kopyası gerekmez.
  • SONSUZ denetimi, Integer.MAX_VALUE toplamının taşmasını (overflow) önler.
  • onceki[i][j] = onceki[k][j]: yeni yolda j'den önceki düğüm, k ⇝ j yolundakiyle aynıdır.
  • Negatif döngü: bir düğümün kendine uzaklığı negatif çıkarsa (D[i][i] < 0).

A* Arama

A* (A Yıldız) Arama Algoritması

  • İki nokta (başlangıç → hedef) arasındaki en kısa yolu bulan bir arama algoritmasıdır.
  • 1968'de Peter Hart, Nils Nilsson ve Bertram Raphael tarafından geliştirildi.
  • Dijkstra'nın (düzgün maliyetli arama) gerçek maliyetini, açgözlü en iyi ilk arama (Greedy Best-First Search) yaklaşımının hedef tahminiyle birleştirir.
  • Düzgün çalışması için iyi bir tahmin fonksiyonu (sezgisel, heuristic) gerekir.
  • Düğüm sayısı arttıkça zaman ve bellek maliyeti hızla artar.
Algoritma ilkeleriHer düğüm için bir tahmin h(n) kullanılır: düğümün hedefe olan tahmini uzaklığı. Her adımda açık listedeki düğümler arasından gerçek maliyet ile tahmini maliyetin toplamı en küçük olan seçilir. Böylece algoritma hedefe doğru ilerlerken en az maliyetli yolu da korur.

A* Arama

A* Nasıl Çalışır? f(n) = g(n) + h(n)

g(n): gerçek maliyetBaşlangıç düğümünden n'ye kadar bulunan yolun maliyeti ("g-maliyet"). Dijkstra'daki d[n] ile aynıdır.
h(n): sezgiseln'den hedefe tahmini maliyet ("h-maliyet"). Kuş uçuşu uzaklık, Manhattan uzaklığı gibi.
f(n) = g(n) + h(n)n üzerinden geçen bir çözümün tahmini toplam maliyeti. Açık listeden en küçük f'li düğüm genişletilir.
Seçim ölçütüAlgoritmaDavranış
yalnızca g(n)Dijkstraher yöne eşit yayılır; doğru ama çok düğüm açar
yalnızca h(n)Açgözlü en iyi ilkhedefe koşar; hızlı ama en kısa yolu garanti etmez
g(n) + h(n)A*hedefe yönelir; h uygunsa en kısa yolu garanti eder
Sezgisel tahminlere göre hedefe yakın görünen düğümler önceliklendirilir; ama g sayesinde pahalı bir yoldan gelen düğüm geri planda kalır.

A* Arama

A*: Algoritma Adımları

1. Başlangıç düğümünü seç, g = 0 ata ve açık listeye (open list, öncelik kuyruğu) ekle. Diğer düğümlerin g değeri ∞.

Açık liste: keşfedilmiş ama henüz genişletilmemiş düğümler.

2. Açık listeden f = g + h değeri en küçük düğümü çıkar ve kapalı listeye (closed list) koy.

Seçim ölçütü g ya da h tek başına değil, toplamları f = g + h'dir.

3. Çıkarılan düğüm hedefse çözüm bulundu: yolu önceki işaretçileriyle geri kur.

Hedef, açık listeye eklendiği anda değil, çıkarıldığı anda kesinleşir.

4. Değilse her komşu için g' = g(u) + w(u, v) hesapla; g' daha küçükse g, f ve önceki değerlerini güncelle, komşuyu açık listeye ekle.

Bu, Dijkstra'daki gevşetmenin aynısıdır.

5. 2. adıma dön. Açık liste boşalırsa hedefe yol yoktur.

Seçim yalnızca son düğümün komşuları arasından değil, açık listenin tamamından yapılır.

A* Arama

Sezgisel Fonksiyonun Özellikleri

Kabul edilebilir (admissible)h(n) ≤ h*(n): gerçek kalan maliyeti asla aşmaz. Bu durumda A* hedefi çıkardığında bulduğu yol en kısadır.
Tutarlı (consistent)h(u) ≤ w(u, v) + h(v) ve h(hedef) = 0. Tutarlı h ile bir düğüm kapalı listeye girdiğinde kesinleşir (yeniden açılmaz).
Izgarada sezgiseller4 yön: Manhattan |Δx| + |Δy|. 8 yön: oktil (octile) 14·min + 10·(max − min). Serbest düzlem: Öklid uzaklığı.
Uç durumlarh = 0 → A* = Dijkstra. h = h* (mükemmel) → yalnızca en kısa yol üzerindeki düğümler açılır. h > h* → hızlı ama en kısa yol garanti edilmez.

A* Arama

A*: Algoritma Karmaşıklığı

  • Arama ağacı açısından en kötü durumda zaman ve bellek O(bd):
    • b: dallanma faktörü (bir düğümün ortalama komşu sayısı), d: hedefin derinliği (çözümdeki adım sayısı).
  • Sonlu bir çizgede tutarlı h ile A*, Dijkstra gibi en fazla O((V + E) log V) iş yapar.
  • Sezgisel ne kadar iyiyse o kadar az düğüm açılır: mükemmel tahminde (h = h*) yalnızca yol üzerindeki d düğüm genişletilir.
  • Zayıf nokta bellektir: açık ve kapalı listeler büyür; IDA*, SMA* gibi türevler bellek sınırlıdır.
Dikkat: O(bd) mükemmel tahminin değil, en kötü durumun (h işe yaramaz, ör. h = 0) sınırıdır; mükemmel tahminde arama yol uzunluğuyla doğrusaldır.

A* Arama

A* Örnek: s'den t'ye (h değerleri düğüm yanında)

1,5234232sdaebcth=4,5h=4h=2h=2h=4hedef

Açık liste

düğümghf
a1,545,5
d24,56,5

Kapalı: s

s genişletilir: komşular a (g = 1,5) ve d (g = 2) açılır. f(a) = 1,5 + 4 = 5,5, f(d) = 2 + 4,5 = 6,5.

1,5234232sdaebcth=4,5h=4h=2h=2h=4hedef

Açık liste

düğümghf
b3,525,5
d24,56,5

Kapalı: s, a

En küçük f: a (5,5). a genişletilir → b: g = 3,5, f(b) = 3,5 + 2 = 5,5.

1,5234232sdaebcth=4,5h=4h=2h=2h=4hedef

Açık liste

düğümghf
d24,56,5
c6,5410,5

Kapalı: s, a, b

b genişletilir (5,5 < 6,5) → c: g = 6,5, f(c) = 6,5 + 4 = 10,5. Bu yol pahalılaşıyor.

1,5234232sdaebcth=4,5h=4h=2h=2h=4hedef

Açık liste

düğümghf
e527
c6,5410,5

Kapalı: s, a, b, d

Artık en küçük f: d (6,5). Arama diğer kola geçer → e: g = 5, f(e) = 5 + 2 = 7.

1,5234232sdaebcth=4,5h=4h=2h=2h=4hedef

Açık liste

düğümghf
t707
c6,5410,5

Kapalı: s, a, b, d, e

e genişletilir → t: g = 5 + 2 = 7, f(t) = 7 + 0 = 7 < f(c) = 10,5.

1,5234232sdaebcth=4,5h=4h=2h=2h=4hedef

Açık liste

düğümghf
c6,5410,5

Kapalı: s, a, b, d, e, t

t açık listeden çıkarıldı: hedef. En kısa yol s → d → e → t, maliyet 7. c hiç genişletilmedi.

A* Arama

A* Örnek: Izgarada Duvarın Etrafından

B142842103848144862103848A105262144862105262145670
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

A genişletilir: 8 komşu açılır. Düz adım 10, çapraz 14; h = oktil uzaklık (duvarlar yok sayılır). En küçük f = 42.

B242448142842103848144862283462103848A105262144862105262145670
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

2. genişletme: en küçük f = 42 olan hücre (turuncu çerçeve) kapalı listeye geçer, komşuları açılır/güncellenir.

B342054242448142842103848144862383068203454103848A105262244468144862105262145670
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

4. genişletme: en küçük f = 48 olan hücre (turuncu çerçeve) kapalı listeye geçer, komşuları açılır/güncellenir.

B244468442468342054242448142842103848144862483482303060203454103848A105262344074244468144862105262145670
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

7. genişletme: en küçük f = 54 olan hücre (turuncu çerçeve) kapalı listeye geçer, komşuları açılır/güncellenir. Duvarın altındaki hücreler f = 42…62 ile önce denenir.

B244468442468342054242448142842103848144862403474303060203454103848A105262444488344074244468144862105262145670285482245882286290
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

9. genişletme: en küçük f = 62 olan hücre (turuncu çerçeve) kapalı listeye geçer, komşuları açılır/güncellenir.

B582482244468285482542882442468342054242448142842103848144862245882583896403474303060203454103848A105262206282444488344074244468144862105262145670246690285482245882206282246690
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

13. genişletme: en küçük f = 68 olan hücre (turuncu çerçeve) kapalı listeye geçer, komşuları açılır/güncellenir. Alt yol tıkalı: f = 68 değerine çıkıldı, arama duvarın iki yanına yayılıyor.

721082621476522476483482524496680B 68581068482068383068344074385088582482244468285482542882442468342054242448142842103848144862245882583896403474303060203454103848A105262206282444488344074244468144862105262145670246690285482245882206282246690
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

17. genişletme (f = 68): duvarın sağından dolaşan yol B'ye ulaştı; B açık listede f = 68.

721082621476522476483482524496680B 68581068482068383068344074385088582482244468285482542882442468342054242448142842103848144862245882583896403474303060203454103848A105262206282444488344074244468144862105262145670246690285482245882206282246690
açıkkapalıyolduvarsol üst g · sağ üst h · orta f

B çıkarıldı: yol A → yukarı → sağ üst çapraz → sol üst çapraz → duvar üstünden üç adım sola, maliyet 68 (2 çapraz × 14 + 4 düz × 10). 18 hücre genişletildi.

İlgili Yöntemler

BFS: Ağırlıksız Çizgede En Kısa Yol

  • Tüm kenarlar eşit (ağırlık 1) ise en kısa yol = en az kenarlı yol.
  • Genişlik öncelikli arama (BFS) düğümleri kaynağa uzaklık sırasıyla, katman katman ziyaret eder: d[v] = d[u] + 1.
  • Kuyruk (FIFO), Dijkstra'nın öncelik kuyruğunun yerini alır: O(V + E).
  • Örnek (yandaki çizge): 0 → 6 en kısa yolu 0 → 2 → 4 → 6 (3 kenar).
  • İki yönlü arama (bidirectional): BFS hem kaynaktan hem hedeften başlatılır, iki dalga buluşunca durulur; yaklaşık 2·bd/2 düğüm açılır.
0172345601112233

Sayılar: BFS seviyesi (kenar sayısı). Yeşil: BFS ağacı.

İlgili Yöntemler

Karıştırılmaması Gereken: Gezgin Satıcı (TSP)

  • En kısa yol: iki düğüm arasında en ucuz yol; Dijkstra ile polinom zamanda çözülür.
  • Gezgin Satıcı Problemi (Travelling Salesman Problem, TSP): tüm şehirleri birer kez ziyaret edip başlangıca dönen en kısa tur.
  • TSP NP-zordur; bilinen kesin algoritmalar üsteldir.
  • Kaba kuvvet (brute force): bir şehir sabitlenir, (n − 1)!/2 tur denenir.
  • En yakın komşu (nearest neighbor) sezgiseli: her adımda en yakın ziyaret edilmemiş şehre git; hızlı (O(n²)) ama en iyiyi garanti etmez.
n şehirfarklı tur (n − 1)!/2
512
10181.440
15≈ 4,36 · 10¹⁰
20≈ 6,08 · 10¹⁶

Ayrıntı: Bölüm 14 (Dal ve Sınır). Simülatörde iki yöntemi karşılaştırabilirsiniz.

Karşılaştırma

En Kısa Yol Algoritmalarının Karşılaştırması

AlgoritmaProblemNegatif kenarNegatif döngüZamanYöntem
BFStek kaynak, ağırlıksız——O(V + E)katman katman
Dijkstratek kaynakhayırhayırO(V²) / O((V + E) log V)açgözlü
Bellman-Fordtek kaynakevettespit ederO(V · E)tekrarlı gevşetme (DP)
Floyd-Warshalltüm çiftlerevettespit ederΘ(V³)dinamik programlama
A*tek çifthayırhayıren kötü O(bd)sezgisel + açgözlü
Ağırlıksız mı?BFS yeterli.
Ağırlıklar ≥ 0?Dijkstra; hedef tek ve iyi h varsa A*.
Negatif kenar?Bellman-Ford.
Tüm çiftler, küçük V?Floyd-Warshall.

Özet

Özet

KonuHatırlanacaklar
Gevşetmed[u] + w < d[v] ise d[v] ve π[v] güncellenir; tüm algoritmaların ortak işlemi
Dijkstraen küçük d'li düğümü kesinleştir, komşularını gevşet; ağırlıklar ≥ 0; O((V + E) log V)
Bellman-Fordtüm kenarları V − 1 tur gevşet; V. turda gevşeyen kenar = negatif döngü; O(V · E)
Floyd-WarshallD[i][j] = min(D[i][j], D[i][k] + D[k][j]), k en dışta; D[i][i] < 0 → negatif döngü; Θ(V³)
A*f = g + h; kabul edilebilir h ile en kısa yol; h = 0 → Dijkstra
BFSağırlıksız çizgede en az kenarlı yol; O(V + E)
Yolπ (Π) işaretçileriyle hedeften geriye; en kısa yol ağacı

Özet

Etkileşimli Simülatörler

En Kısa Yol AlgoritmalarıRastgele bağlı, ağırlıklı bir çizge üretin; Dijkstra, Bellman-Ford ve Floyd-Warshall'ı A düğümünden son düğüme çalıştırıp adım günlüğünü karşılaştırın. Düğümler sürüklenebilir.
A* Yol BulmaIzgaraya tıklayarak duvar ekleyip kaldırın, A*'ı çalıştırın; keşfedilen hücreleri ve bulunan en kısa yolu izleyin (4 yön, Manhattan sezgiseli).
Gezgin Satıcı ProblemiŞehirler üretin; hızlı en yakın komşu sezgiselini kesin kaba kuvvet aramasıyla karşılaştırın ve tur uzunluklarını görün.

Özet

Sık Yapılan Hatalar

Negatif kenarda DijkstraKesinleşmiş bir düğüme sonradan daha kısa yol açılabilir; sonuç sessizce yanlış olur. Bellman-Ford kullanın.
∞ + w taşmasıInteger.MAX_VALUE + w negatife döner ve “daha kısa” görünür. Önce d[u] != SONSUZ denetleyin.
Floyd-Warshall döngü sırasık ara düğüm döngüsü en dışta olmalı; i, j, k sırası yanlış sonuç verir.
Tur sayısıBellman-Ford'da V − 1 tur gerekebilir (Örnek 2); tek turda biteceğini varsaymayın. Denetim turu ayrıdır.
A*'da hedefte durmakHedef açık listeye eklendiğinde değil, listeden çıkarıldığında durulur. Fazla tahmin eden h en kısa yolu kaçırır.
Yönsüz kenarda negatif ağırlıkYönsüz negatif kenar u → v → u ile kendi başına negatif döngüdür.

Özet

Örnek Problemler

Yönlü çizge: A→B 4, A→C 2, C→B 1, B→D 5, C→D 8, C→E 10, D→E 3; kaynak A.

  1. Dijkstra düğümleri hangi sırayla kesinleştirir? Son d değerleri nedir?
  2. A'dan E'ye en kısa yolu π dizisiyle yazın.
  3. Kenarlar yukarıdaki alfabetik sırayla (A→B, A→C, B→D, C→B, C→D, C→E, D→E) incelenirse Bellman-Ford'un her turunda kaç gevşetme olur?
  4. 1→2 (4), 2→3 (1), 1→3 (7), 3→1 (−2) çizgesinin Floyd-Warshall son D matrisi nedir? Negatif döngü var mı?
  5. V = 1000, E = 5000 ve negatif kenarlar var. Hangi algoritma, yaklaşık kaç işlem?
Cevapları göster
  1. A, C, B, D, E; d = A:0, B:3, C:2, D:8, E:11 (B, C üzerinden 2 + 1 ile iyileşir).
  2. π[E] = D, π[D] = B, π[B] = C, π[C] = A → A → C → B → D → E = 2 + 1 + 5 + 3 = 11.
  3. Tur 1: 5 (B=4, C=2, D=9, B=3, E=12); tur 2: 2 (D=8, E=11); tur 3–4: 0 → erken durma mümkün.
  4. D = [[0, 4, 5], [−1, 0, 1], [−2, 2, 0]]; köşegen 0 → döngü 1→2→3→1 = +3, negatif döngü yok.
  5. Bellman-Ford: V · E = 1000 · 5000 = 5 · 10⁶ gevşetme denemesi (Dijkstra negatif kenarda güvenilmez).

Özet

Alıştırmalar

  1. Dijkstra Örnek 1'deki çizgede kaynağı 5 alarak tüm uzaklıkları bulun.
  2. dijkstra(kaynak, hedef): hedef kuyruktan çıkınca duran sürümü yazın.
  3. Her düğüm için en kısa yol sayısını da hesaplayan Dijkstra yazın.
  4. Bellman-Ford'a erken durma ekleyin; en iyi durumda karmaşıklık nedir?
  5. Floyd-Warshall'ı boolean matrisle geçişli kapanış (Warshall) için uyarlayın.
  6. Manhattan uzaklığı 4 yönlü ızgarada neden kabul edilebilir, 8 yönlüde neden değildir?
Cevaplar / ipuçları
  1. d = 1:20, 2:21, 3:11, 4:6, 5:0, 6:9 (ör. 3: 5→6→3 = 9 + 2; 2: 5→4→2 = 6 + 15).
  2. Satır 13'ten önce if (u == hedef) break; — eklenme anında değer henüz kesin değildir.
  3. sayi[kaynak] = 1; d[u] + w < d[v] ise sayi[v] = sayi[u], eşitse sayi[v] += sayi[u].
  4. degisti bayrağı false kalırsa çıkın; en iyi durum O(E).
  5. t[i][j] = t[i][j] || (t[i][k] && t[k][j]); yine k en dışta, Θ(V³).
  6. Her adım |Δx| + |Δy|'yi en çok 1 azaltır → h ≤ h*. Çapraz adım 2 azaltır ama 1 (ya da 1,4) tutar → fazla tahmin.

Özet

Kaynaklar

  • Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022 (Bölüm 22–23).
  • Sedgewick ve Wayne, Algorithms, 4. baskı, 2011 (Bölüm 4.4: Shortest Paths).
  • E. W. Dijkstra, "A Note on Two Problems in Connexion with Graphs", Numerische Mathematik 1, 1959.
  • R. Bellman, "On a Routing Problem", Quarterly of Applied Mathematics 16, 1958.
  • R. W. Floyd, "Algorithm 97: Shortest Path", Communications of the ACM 5(6), 1962; S. Warshall, "A Theorem on Boolean Matrices", Journal of the ACM 9(1), 1962.
  • P. E. Hart, N. J. Nilsson ve B. Raphael, "A Formal Basis for the Heuristic Determination of Minimum Cost Paths", IEEE Trans. SSC 4(2), 1968.

Son

Bölüm 4.2: En Kısa Yol Algoritmaları
Önceki bölüm: Bölüm 4.1: Çizge Gezinme Algoritmaları · Sonraki bölüm: Bölüm 4.3: Minimum Kapsayan Ağaç Algoritmaları
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.