Bölüm 4.3: Minimum Kapsayan Ağaç Algoritmaları

Algoritmalar
Kapsayan ağaçKesme ve döngü özelliğiKruskalUnion-Find PrimBorůvkaTers silmeKarşılaştırma
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Kavram

Kapsayan ağacı ve minimum kapsayan ağacı (MST) tanımlamak; V − 1 kenar, kesme ve döngü özelliklerini açıklamak.

Kruskal ve Union-Find

Kenarları sıralayıp döngü oluşturmayanları seçmek; döngü denetimini ayrık kümelerle (bul / birleştir) yapmak.

Prim

Ağacı bir düğümden büyütmek; anahtar ve ata dizilerini öncelik kuyruğuyla adım adım izlemek.

Borůvka, Ters Silme, Analiz

Bileşen tabanlı ve silme tabanlı yaklaşımları uygulamak; dört algoritmanın karmaşıklığını karşılaştırıp uygun olanı seçmek.

MST Kavramı

Kapsayan Ağaç ve Minimum Kapsayan Ağaç

  • G = (V, E): bağlı, yönsüz ve kenarları ağırlıklı bir çizge.
  • Kapsayan ağaç (spanning tree): tüm düğümleri içeren, bağlı ve döngüsüz alt çizge. Her zaman tam V − 1 kenarı vardır.
  • Minimum kapsayan ağaç (Minimum Spanning Tree, MST): kenar ağırlıkları toplamı en küçük olan kapsayan ağaç.
  • Ağaca bir kenar eklemek döngü oluşturur; bir kenar silmek ağacı ikiye böler.
3154276aebcd
Bir çizgenin çok sayıda kapsayan ağacı olabilir (n düğümlü tam çizgede nn−2 tane, Cayley formülü). Hepsini denemek yerine açgözlü (greedy) algoritmalar MST'yi doğrudan bulur. Yandaki çizgede MST ağırlığı w(T) = 1 + 2 + 3 + 5 = 11.

MST Kavramı

Örnek: "MST" Çizgesi

152251610781011254118202524124050
  • 15 düğüm, 20 kenar. Kalın 14 kenar (= V − 1) minimum kapsayan ağacı oluşturur: toplam ağırlık 141.
  • İnce kenarlar dışarıda kalır: her biri, kalın kenarlarla bir döngü kapatır ve o döngünün en ağır kenarıdır (ör. 15, 16, 18, 25, 40, 50).
  • Ağırlığı yüksek (20, 24, 25) kenarlar da seçilebilir: bir düğüme ulaşmanın tek yolu onlarsa (köprü) MST'de yer almak zorundadır.

MST Kavramı

Kesme Özelliği ve Döngü Özelliği

Kesme özelliği (cut property)Düğümleri iki kümeye ayıran her kesmede, kesmeyi geçen en hafif kenar bir MST'ye aittir.
kesme3154276aebcd

{a, b} | {c, d, e}: geçen kenarlar ae = 1, be = 4, bc = 5 → ae güvenli.

Döngü özelliği (cycle property)Herhangi bir döngünün en ağır kenarı (tekse) hiçbir MST'de yer almaz.
3154276aebcd

b–c–e döngüsü: 4, 5, 6 → ec = 6 asla seçilmez.

Kruskal ve Prim kesme özelliğini, ters silme döngü özelliğini kullanır. Tüm ağırlıklar farklıysa MST tektir.

MST Kavramı

Açgözlü MST Algoritmaları

Dört algoritmanın hepsi açgözlüdür: her adımda yerel olarak en iyi kenarı seçer (ya da en kötüsünü atar) ve bu seçim hiçbir zaman geri alınmaz.

AlgoritmaFikirYardımcı yapıZaman
Kruskal (1956)Kenarları küçükten büyüğe sırala, döngü oluşturmayanları ekleunion-findO(E log E)
Prim (1957)Bir düğümden başla, ağacı en ucuz komşu kenarla büyütöncelik kuyruğuO((V + E) log V)
Borůvka (1926)Her bileşen kendi en ucuz kenarını aynı anda eklerunion-findO(E log V)
Ters silmeKenarları büyükten küçüğe dene, bağlılığı bozmayanı silBFS/DFS ya da union-findO(E · (V + E))
Hepsi aynı ağırlıkta bir MST bulur; ağırlıklar farklıysa aynı ağacı bulurlar. Fark, kenarları hangi sırayla ele aldıkları ve gereken veri yapısındadır.

MST Kavramı

Nerede Kullanılır?

Ağ tasarımıŞehirleri en az kabloyla bağlamak: elektrik, su, fiber, yol ağları. Borůvka'nın çıkış noktası Moravya'nın elektrik ağıdır.
KümelemeMST'den en ağır k − 1 kenar silinirse k küme kalır (tek bağlantılı kümeleme, single-linkage).
Yaklaşık algoritmalarMetrik gezgin satıcı probleminde (TSP) MST tabanlı tur, en iyinin en fazla 2 katıdır.
Görüntü işlemePikselleri düğüm, renk farkını ağırlık sayarak bölütleme (segmentation).
Devre tasarımıBacakları en kısa toplam iletkenle bağlamak (VLSI yönlendirme ön adımı).
Diğer çizge problemleriDarboğaz yol (en büyük kenarı en küçük yol) MST üzerindedir; Steiner ağacı için temel yaklaşım.

Kruskal

Kruskal Algoritması

  • Çizgedeki tüm düğümleri birbirine bağlayan, toplam ağırlığı en küçük ağacı oluşturur; açgözlü (greedy) bir yaklaşımdır.
  • Joseph Kruskal tarafından geliştirilmiştir (1956).
  • Başlangıçta her düğüm ayrı bir ağaçtır (orman); adım adım bu ağaçlar birleştirilir.
  • Kenarlar küçükten büyüğe sıralanır; döngü oluşturmayan kenar seçilir, döngü oluşturan atlanır.

Güçlü yönler

  • Seyrek çizgelerde (E ≈ V) çok uygun.
  • Basit: kenar listesi + union-find yeterli.
  • Bağlı olmayan çizgede minimum kapsayan orman verir.

Zayıf yönler

  • Kenar sıralama maliyeti: O(E log E).
  • Yoğun çizgede (E ≈ V²) Prim daha hızlı olabilir.
  • Döngü denetimi için ek yapı (union-find) gerekir.

Kruskal

Kruskal: Adımlar ve Sözde Kod

  1. Çizgedeki tüm kenarlar ağırlıklarına göre sıralanır.
  2. Sıralı kenarlar arasından sıradaki en küçük ağırlıklı kenar seçilir.
  3. Kenar farklı ağaçlara ait iki düğümü birleştiriyorsa (döngü oluşturmuyorsa) ağaca eklenir ve iki ağaç birleştirilir.
  4. Aynı ağacın iki düğümünü bağlıyorsa döngü oluşturur: atlanır.
  5. V − 1 kenar seçilene (ya da kenarlar bitene) kadar 2–4 tekrarlanır.
KRUSKAL(G):
  MST = [ ]
  ayrikKume.oluştur(V)
  kenarlar.sırala(artana göre)
  her bir (u, v, ağırlık) için kenarlar içinde:
    eğer ayrikKume.bul(u) ≠ ayrikKume.bul(v):
      MST.ekle((u, v, ağırlık))
      ayrikKume.birleştir(u, v)
  döndür MST

"Aynı ağaçta mı?" sorusu union-find (ayrık kümeler) yapısıyla neredeyse sabit zamanda yanıtlanır.

Kruskal

Kruskal Adım Adım

ab3ae1bc5be4cd2ed7ec63154276aebcd
MST—
w(T)0
Ağaçlar{a} {b} {c} {d} {e}

Başlangıç: her düğüm ayrı bir ağaçtır (5 ağaçlı orman). Kenar tablosu henüz sırasız.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MST—
w(T)0
Ağaçlar{a} {b} {c} {d} {e}

Adım 1: kenarlar artan ağırlığa göre sıralanır: ae, cd, ab, be, bc, ec, ed.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MSTae
w(T)1
Ağaçlar{a, e} {b} {c} {d}

ae = 1: a ve e farklı ağaçlarda → kenar eklenir, iki ağaç birleşir.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MSTae, cd
w(T)3
Ağaçlar{a, e} {c, d} {b}

cd = 2: c ve d farklı ağaçlarda → kenar eklenir, iki ağaç birleşir.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MSTae, cd, ab
w(T)6
Ağaçlar{a, b, e} {c, d}

ab = 3: a ve b farklı ağaçlarda → kenar eklenir, iki ağaç birleşir.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MSTae, cd, ab
w(T)6
Ağaçlar{a, b, e} {c, d}

be = 4: b ve e zaten aynı ağaçta → eklenirse döngü oluşur, atlanır.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MSTae, cd, ab, bc
w(T)11
Ağaçlar{a, b, c, d, e}

bc = 5: b ve c farklı ağaçlarda → kenar eklenir, iki ağaç birleşir.

ae1cd2ab3be4bc5ec6ed73154276aebcd
MSTae, cd, ab, bc
w(T)11
Ağaçlartek ağaç

V − 1 = 4 kenar seçildi: ağaç kuruldu, w(T) = 11. ec ve ed'ye bakmaya gerek yoktur.

Kruskal

Union-Find (Ayrık Kümeler, Disjoint Set)

  • Kesişmeyen kümeleri tutar. Her küme bir ağaçtır; kökü kümenin temsilcisidir. ata[i]: i'nin ebeveyni, kökte ata[r] = r.
  • oluştur(V): her düğüm kendi kümesi → ata[i] = i.
  • bul(x) (find): köke kadar çık, kökü döndür.
  • birleştir(x, y) (union): bir kökü diğerinin altına bağla.
  • Kruskal'da: bul(u) == bul(v) ise u ve v aynı ağaçtadır → kenar döngü kapatır.
int bul(int[] ata, int i) {
  if (ata[i] != i)
    ata[i] = bul(ata, ata[i]); // yol sıkıştırma
  return ata[i];
}
void birlestir(int[] ata, int x, int y) {
  ata[bul(ata, x)] = bul(ata, y);
}
İki iyileştirme: yol sıkıştırma (path compression) ve rütbeye göre birleştirme (union by rank). İkisi birlikte işlem başına amortize O(α(V)) verir; α (ters Ackermann) pratikte ≤ 4'tür.

Kruskal

Union-Find ile Döngü Denetimi

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]aabbccddee

oluştur(5): her düğüm kendi kümesinin kökü, ata[i] = i. Kenarlar: ac 1, de 2, ab 3, bc 4, bd 5, cd 6, ce 7.

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]cabbccddee

ac = 1: bul(a) = a, bul(c) = c → farklı → kenar MST'ye; ata[a] = c.

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]cabbccedee

de = 2: bul(d) = d, bul(e) = e → farklı → kenar MST'ye; ata[d] = e.

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]cabbbcedee

ab = 3: bul(a) = c, bul(b) = b → farklı → kenar MST'ye; ata[c] = b.

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]cabbbcedee

bc = 4: bul(b) = b (yol b), bul(c) = b → aynı kök: döngü, kenar atlanır.

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]caebbcedee

bd = 5: bul(b) = b, bul(d) = e → farklı → kenar MST'ye; ata[b] = e.

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]caebbcedee

MST tamam (4 kenar, w = 11). Ama orman uzun bir zincir oldu: bul(a) a→c→b→e yolunu izler (3 adım).

1234567acbdeAyrık küme ormanı (ok: ata)abcdeata[ ]eaebecedee

Yol sıkıştırma: bul(a) dönerken yoldaki her düğümü doğrudan köke bağlar (ata[a] = ata[c] = e). Sonraki aramalar 1 adım.

Kruskal · Kodu adım adım çalıştır

Kruskal: Kodu Adım Adım İzle

22344612534

Kenarlar sıralanır: (1,3)=2, (2,5)=2, (1,2)=3, (2,3)=4, (3,4)=4, (1,4)=6.

22344612534

ata[i] = i: her düğüm ayrı bir ağaç (5 ağaç).

22344612534

e = (1,3), ağırlık 2: bul(1) = 1, bul(3) = 3.

22344612534

x ≠ y → (1,3) MST'ye eklenir, ata[1] = 3. v1 ve v3 birleşir.

22344612534

e = (2,5), ağırlık 2: bul(2) = 2, bul(5) = 5.

22344612534

x ≠ y → (2,5) MST'ye eklenir, ata[2] = 5. v2 ve v5 birleşir.

22344612534

e = (1,2), ağırlık 3: bul(1) = 3, bul(2) = 5.

22344612534

x ≠ y → (1,2) MST'ye eklenir, ata[3] = 5. Önceki iki ağaç birleşir.

22344612534

e = (2,3), ağırlık 4: bul(2) = 5, bul(3) = 5.

22344612534

x = y = 5: (2,3) iki ayrı ağacı birleştirmiyor → döngü, atlanır.

22344612534

e = (3,4), ağırlık 4: bul(3) = 5, bul(4) = 4.

22344612534

x ≠ y → (3,4) MST'ye eklenir, ata[5] = 4. v4 ağaca katılır; w(T) = 11.

22344612534

agac.size() = 4 = V − 1: döngü biter. (1,4)=6 hiç incelenmez. w(T) = 11.

void kruskal(int V, List<Kenar> ke) {
  Collections.sort(ke);         // artan
  int[] ata = new int[V + 1];
  for (int i = 1; i <= V; i++) ata[i] = i;
  List<Kenar> agac = new ArrayList<>();
  int k = 0;
  while (agac.size() < V - 1) {
    Kenar e = ke.get(k++);
    int x = bul(ata, e.u);
    int y = bul(ata, e.v);
    if (x != y) {               // ayrı ağaç
      agac.add(e);
      ata[x] = y;               // birleştir
    }
  }
}

Kruskal

Kruskal Örneği: Dokuz Düğüm

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: tek düğümlüler · Ağırlık: 0 · Bağlı: HAYIR

Kenarlar sıralı: 1, 1, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 15, 20. Henüz hiçbir kenar seçilmedi.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {E, F} · Ağırlık: 1 · Bağlı: HAYIR

EF = 1 eklendi (iki farklı küme). Toplam ağırlık 1.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, E, F} · Ağırlık: 2 · Bağlı: HAYIR

CF = 1 eklendi (iki farklı küme). Toplam ağırlık 2.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, D, E, F} · Ağırlık: 4 · Bağlı: HAYIR

DE = 2 eklendi (iki farklı küme). Toplam ağırlık 4.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, D, E, F, H} · Ağırlık: 7 · Bağlı: HAYIR

FH = 3 eklendi (iki farklı küme). Toplam ağırlık 7.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, D, E, F, H} {A, B} · Ağırlık: 11 · Bağlı: HAYIR

AB = 4 eklendi (iki farklı küme). Toplam ağırlık 11.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, D, E, F, H} {A, B} · Ağırlık: 11 · Bağlı: HAYIR

EH = 5: E ve H zaten aynı kümede (E–F–H yolu) → döngü, eklenmez. Toplam 11 kalır.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, D, E, F, H} {A, B} {G, I} · Ağırlık: 16 · Bağlı: HAYIR

GI = 5 eklendi (iki farklı küme). Toplam ağırlık 16.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {C, D, E, F, G, H, I} {A, B} · Ağırlık: 22 · Bağlı: HAYIR

DG = 6 eklendi (iki farklı küme). Toplam ağırlık 22.

EF1CF1DE2FH3AB4EH5GI5DG6AC7BD9EG10BC11HI12EI15BF2047119201126101553512ABCDEFGHIKümeler: {A, B, C, D, E, F, G, H, I} · Ağırlık: 29 · Bağlı: EVET

AC = 7 eklendi (iki farklı küme). Toplam ağırlık 29. 8 = V − 1 kenar: MST = 29, çizge bağlı.

Kruskal

Kruskal: Karmaşıklık Analizi

İşlemKaç kezMaliyet
Kenarları ağırlığa göre sıralama1O(E log E)
oluştur(V)1O(V)
bul (her kenar için 2)≤ 2EO(E · α(V)) — yol sıkıştırma + rütbe
O(E log V) — yalnızca rütbe
birleştirV − 1
  • Toplam: O(E log E); sıralama baskındır. E ≤ V² olduğundan log E ≤ 2 log V, yani O(E log E) = O(E log V).
  • Kenarlar zaten sıralıysa (ya da ağırlıklar küçük tamsayıysa, sayma sıralaması) süre neredeyse doğrusal: O(E · α(V)).
  • Bellek: kenar listesi + ata dizisi → O(V + E).
Union-find işlemleri yalnızca rütbeye göre birleştirmeyle en kötü O(log V) sürer; yol sıkıştırma da eklenince işlem başına amortize maliyet O(α(V)) olur. Her iki durumda da toplamı sıralama belirler.

Prim

Prim Algoritması

  • Tüm düğümleri bağlayan en küçük ağırlıklı ağacı oluşturur; açgözlü bir algoritmadır.
  • Robert C. Prim (1957); daha önce V. Jarník (1930) bulmuş, E. W. Dijkstra (1959) yeniden keşfetmiştir.
  • Bir başlangıç düğümü seçilir; her adımda ağaçta olmayan düğümler arasından, ağaca en ucuz kenarla bağlanan düğüm ağaca eklenir.
  • Her an tek bir ağaç vardır (Kruskal'daki ormandan farklı olarak).

Güçlü yönler

  • Yoğun çizgelerde uygun: matrisle O(V²).
  • Kenar sıralaması gerekmez.
  • Komşuluk listesi/matrisi ile doğal çalışır.

Zayıf yönler

  • Performans veri yapısına bağlı (dizi, ikili yığın, Fibonacci yığını).
  • Bağlı olmayan çizgede yalnızca başlangıcın bileşenini kapsar.

Prim

Prim: Adımlar, Anahtar ve Ata

  1. Başlangıç düğümü seçilir ve bu düğüme ait tüm kenarlar öncelik kuyruğuna eklenir.
  2. Kuyruktan, ağaçta olmayan bir düğüme giden en küçük ağırlıklı kenar seçilir.
  3. Seçilen kenar ile bağlantılı yeni düğüm ağaca eklenir.
  4. Yeni düğüme bağlı kenarlar kuyruğa eklenir; tüm düğümler ağaca girene kadar 2–4 tekrarlanır.
anahtar[v] (key)v'yi ağaca bağlayan şimdiye kadarki en ucuz kenarın ağırlığı. Başta ∞, kaynakta 0.
ata[v] (π, parent)Bu en ucuz kenarın ağaçtaki ucu. Sonunda (ata[v], v) kenarları MST'yi verir.

Kuyruktan çıkan düğüm için, ağaçta olmayan her komşu v'de: ağırlık(u, v) < anahtar[v] ise anahtar ve ata güncellenir.

Prim

Prim: Sözde Kod

PRIM(G, kaynak):
  MST = [ ]
  mesafeler = [ ]
  ata = [ ]
  ziyaretEdildi = [ ]
  her bir v için V içinde:
    mesafeler[v] = ∞
    ziyaretEdildi[v] = 0
  mesafeler[kaynak] = 0
  öncelikKuyruğu.ekle(kaynak, 0)
döngü öncelikKuyruğu boş değil iken:
  u = öncelikKuyruğu.çıkar()
  eğer ziyaretEdildi[u] == 0:
    ziyaretEdildi[u] = 1
    her bir (u, v, ağırlık) için G[u] içinde:
      eğer ziyaretEdildi[v] == 0 ve
           ağırlık < mesafeler[v]:
        mesafeler[v] = ağırlık
        ata[v] = u
        öncelikKuyruğu.ekle(v, ağırlık)
her bir v için V içinde (kaynak hariç):
  MST.ekle((ata[v], v, mesafeler[v]))
döndür MST

Bu "tembel" (lazy) sürüm bir düğümü kuyruğa birden çok kez ekleyebilir; ziyaretEdildi denetimi eski kayıtları atar. Kuyruk en fazla E kayıt tutar → O(E log E).

Prim

Prim Adım Adım: Öncelik Kuyruğu

22344612534
keyuπ
01/
∞2/
∞3/
∞4/
∞5/

w(T) = 0

İlklendirme: kuyruk Q tüm düğümlerle başlatılır; key(1) = 0, diğerleri ∞, π = /.

22344612534
keyuπ
231
321
641
∞5/

w(T) = 0

Kuyruktan düğüm 1 çıkar. Komşular güncellenir: key(3) = 2 (1,3), key(2) = 3 (1,2), key(4) = 6 (1,4).

22344612534
keyuπ
321
443
∞5/

w(T) = 2

Düğüm 3 çıkar, T'ye (1,3) eklenir. key(4) = 4 (3,4) olur; (2,3) = 4 > key(2) = 3 → değişmez.

22344612534
keyuπ
252
443

w(T) = 5

Düğüm 2 çıkar, T'ye (1,2) eklenir. key(5) = 2 (2,5).

22344612534
keyuπ
443

w(T) = 7

Düğüm 5 çıkar, T'ye (2,5) eklenir. Ağaçta olmayan komşusu yok: Q'da güncelleme yok.

22344612534
keyuπ
Q = ∅

w(T) = 11

Düğüm 4 çıkar, T'ye (3,4) eklenir. Q'da güncelleme yok.

22344612534
keyuπ
Q = ∅

w(T) = 11

Son durum: Q = ∅. MST = (1,3), (1,2), (2,5), (3,4), w(T) = 11 — Kruskal ile aynı ağaç.

Kesikli çizgi: π ile gösterilen, henüz kesinleşmemiş en ucuz bağlantı. Q tablosu key değerine göre sıralıdır.

Prim · Kodu adım adım çalıştır

Prim: Kodu Adım Adım İzle (Komşuluk Matrisi)

1332654432ABCDEF

A–F çizgesi, kaynak B (indis 1). Tüm anahtarlar ∞; anahtar[B] = 0, ata[B] = −1.

1332654432ABCDEF

enKucukAnahtar → u = B (anahtar 0): kaynak ağaca girer.

1332654432ABCDEF

v = A: G[B][A] = 1 < anahtar[A] = ∞ → anahtar[A] = 1, ata[A] = B.

1332654432ABCDEF

v = C: G[B][C] = 3 < anahtar[C] = ∞ → anahtar[C] = 3, ata[C] = B.

1332654432ABCDEF

v = D: G[B][D] = 2 < anahtar[D] = ∞ → anahtar[D] = 2, ata[D] = B.

1332654432ABCDEF

v = E: G[B][E] = 6 < anahtar[E] = ∞ → anahtar[E] = 6, ata[E] = B.

1332654432ABCDEF

v = F: G[B][F] = 5 < anahtar[F] = ∞ → anahtar[F] = 5, ata[F] = B.

1332654432ABCDEF

enKucukAnahtar → u = A (anahtar 1); (B,A) ağaca girer. w(T) = 1. AD = 3 > anahtar[D] = 2: güncelleme yok.

1332654432ABCDEF

enKucukAnahtar → u = D (anahtar 2); (B,D) ağaca girer. w(T) = 3.

1332654432ABCDEF

v = E: G[D][E] = 3 < anahtar[E] = 6 → anahtar[E] = 3, ata[E] = D.

1332654432ABCDEF

enKucukAnahtar → u = C (anahtar 3); (B,C) ağaca girer. w(T) = 6. C ve E eşit (3): küçük indisli C.

1332654432ABCDEF

v = F: G[C][F] = 4 < anahtar[F] = 5 → anahtar[F] = 4, ata[F] = C.

1332654432ABCDEF

enKucukAnahtar → u = E (anahtar 3); (D,E) ağaca girer. w(T) = 9.

1332654432ABCDEF

v = F: G[E][F] = 2 < anahtar[F] = 4 → anahtar[F] = 2, ata[F] = E.

1332654432ABCDEF

Döngü V − 1 = 5 kez döndü; son düğüm F'nin ata'sı E. MST = (ata[v], v): AB, BC, BD, DE, EF → w(T) = 11.

void prim(int[][] G, int kaynak) {
  int V = G.length;
  int[] anahtar = new int[V];
  int[] ata = new int[V];
  boolean[] agacta = new boolean[V];
  Arrays.fill(anahtar, Integer.MAX_VALUE);
  anahtar[kaynak] = 0;
  ata[kaynak] = -1;
  for (int s = 0; s < V - 1; s++) {
    int u = enKucukAnahtar(anahtar, agacta);
    agacta[u] = true;
    for (int v = 0; v < V; v++)
      if (G[u][v] != 0 && !agacta[v]
          && G[u][v] < anahtar[v]) {
        anahtar[v] = G[u][v];
        ata[v] = u;
      }
  }
}

Prim

Prim Örneği: Dokuz Düğüm (A'dan Başla)

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar047∞∞∞∞∞∞
ata−AA−−−−−−

Başlangıç A: komşuları B (4) ve C (7) aday olur.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar0479∞20∞∞∞
ata−AAB−B−−−

B ağaca girer: (A,B) = 4, toplam 4. Güncellenen: D → 9, F → 20.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar0479∞1∞∞∞
ata−AAB−C−−−

C ağaca girer: (A,C) = 7, toplam 11. Güncellenen: F → 1.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar047911∞3∞
ata−AABFC−F−

F ağaca girer: (C,F) = 1, toplam 12. Güncellenen: E → 1, H → 3.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar04721110315
ata−AAEFCEFE

E ağaca girer: (F,E) = 1, toplam 13. Güncellenen: D → 2, G → 10, I → 15.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar0472116315
ata−AAEFCDFE

D ağaca girer: (E,D) = 2, toplam 15. Güncellenen: G → 6.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar0472116312
ata−AAEFCDFH

H ağaca girer: (F,H) = 3, toplam 18. Güncellenen: I → 12. EH = 5 artık kullanılamaz: E ve H ikisi de ağaçta (döngü).

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar047211635
ata−AAEFCDFG

G ağaca girer: (D,G) = 6, toplam 24. Güncellenen: I → 5.

47119201126101553512ABCDEFGHI
ABCDEFGHI
anahtar047211635
ata−AAEFCDFG

I ağaca girer: (G,I) = 5, toplam 29. Tüm düğümler ağaçta: MST = 29 (Kruskal ile aynı).

Prim

Prim: Karmaşıklık Analizi

Uygulamaen küçüğü çıkaranahtar azaltToplam
Komşuluk matrisi + dizi taraması (yukarıdaki kod)V × O(V)O(1)O(V²)
Komşuluk listesi + ikili yığın (binary heap)V × O(log V)E × O(log V)O((V + E) log V)
Tembel sürüm (sözde kod): kuyrukta kenar kopyaları≤ E ekleme/çıkarma, her biri O(log E)O(E log E)
Fibonacci yığınıO(log V) amortizeO(1) amortizeO(E + V log V)
Yoğun çizge (E ≈ V²)Matris sürümü O(V²) en iyisidir; yığın sürümü O(V² log V) olur.
Seyrek çizge (E ≈ V)Yığın sürümü O(V log V); matris sürümü gereksiz yere O(V²).

Prim

Prim ile Dijkstra Arasındaki Fark

İki algoritmanın kodu neredeyse aynıdır (Bölüm 4.2): bir kaynaktan başlar, öncelik kuyruğundan en küçük anahtarlı düğümü çıkarır ve komşuları gevşetir. Tek fark anahtarın anlamıdır.

Prim (MST)Dijkstra (en kısa yol)
anahtar[v]v'yi ağaca bağlayan en ucuz tek kenarkaynaktan v'ye toplam yol uzunluğu
Güncellemew(u,v) < anahtar[v]uzaklik[u] + w(u,v) < uzaklik[v]
Sonuçtoplam ağırlığı en küçük ağaçen kısa yollar ağacı (SPT)
Kaynaksonucu etkilemez (aynı ağırlık)sonucu belirler
Negatif ağırlıksorun değilçalışmaz

Beş düğümlü örnekte 1'den en kısa yollar ağacı (1,4) = 6 kenarını kullanabilir; MST onun yerine (3,4) = 4'ü seçer.

Borůvka

Borůvka (Sollin) Algoritması

  • Minimum kapsayan ağacı bulan en eski algoritma: Otakar Borůvka, 1926 (Moravya elektrik ağı). Diğer adı Sollin algoritması.
  • Başlangıçta her düğüm bağımsız bir bileşendir.
  • Her turda her bileşen kendisini dışarıya bağlayan en ucuz kenarı seçer; seçilenlerin hepsi birden eklenir.
  • Bileşenler union-find ile birleştirilir; tek bileşen kalana kadar devam edilir. Bağlı çizgede |V| − 1 kenar üretir.

Güçlü yönler

  • Bileşenlerin seçimleri birbirinden bağımsız: paralel çalışmaya çok uygun.
  • Tur sayısı en fazla ⌈log₂ V⌉.

Zayıf yönler

  • Kruskal/Prim'den daha karmaşık kodlanır.
  • Eşit ağırlıklarda tutarlı bir eşitlik bozucu (ör. kenar indisi) şart; yoksa döngü oluşabilir.

Borůvka

Borůvka: Adımlar ve Sözde Kod

  1. Başlangıçta her düğümü tek başına bir bileşen (küme) olarak ele al.
  2. Her bileşen için, onu başka bir bileşene bağlayan en küçük ağırlıklı kenarı bul.
  3. Bulunan kenarların hepsini ekle; bağladıkları bileşenleri birleştir (aynı kenar iki kez eklenmez).
  4. Tek bileşen kalana kadar 2 ve 3. adımları tekrarla.

Not: Borůvka kenarları sıralamaz; her turda tüm kenarları bir kez tarayıp bileşen başına en küçüğü tutar.

BORUVKA(G):
  MST = [ ]
  bileşenSayısı = |V|
  döngü bileşenSayısı > 1 iken:
    enUcuz = [ ]  // bileşen başına
    her bir e = (u, v, ağırlık) için E içinde:
      cu = ayrikKume.bul(u)
      cv = ayrikKume.bul(v)
      eğer cu ≠ cv:
        enUcuz[cu] = min(enUcuz[cu], e)
        enUcuz[cv] = min(enUcuz[cv], e)
    her bir (u, v, ağırlık) için enUcuz içinde:
      eğer ayrikKume.bul(u) ≠ ayrikKume.bul(v):
        MST.ekle((u, v, ağırlık))
        ayrikKume.birleştir(u, v)
        bileşenSayısı -= 1
  döndür MST

Borůvka

Borůvka Adım Adım: Altı Düğüm

154736982ABCDEF

Başlangıç: her düğüm ayrı bir bileşen (6 bileşen).

154736982ABCDEF
BileşenEn ucuz
{A}AB 1
{B}AB 1
{C}BC 5
{D}AD 4
{E}EF 2
{F}EF 2

Tur 1: her bileşen kendi en ucuz dış kenarını seçer (mavi). AB ve EF iki bileşen tarafından seçilir ama birer kez eklenir.

154736982ABCDEF

Tur 1 sonu: 4 farklı kenar eklendi (AB, BC, AD, EF), 2 bileşen kaldı: {A, B, C, D} {E, F}. Toplam 12.

154736982ABCDEF
BileşenEn ucuz
{A,B,C,D}BE 3
{E,F}BE 3

Tur 2: her bileşen kendi en ucuz dış kenarını seçer (mavi). İki bileşen de aynı kenarı seçer.

154736982ABCDEF

Tur 2 sonu: 1 farklı kenar eklendi (BE), 1 bileşen kaldı: {A, B, C, D, E, F}. Toplam 15. MST = 15 (AB, BC, AD, EF, BE).

Kruskal kenarları 1, 2, 3, 4, 5 sırasıyla tek tek ekler; Borůvka'da ise tur 1'de dört kenar aynı anda eklenir. Sonuç ağacı aynıdır.

Borůvka

Borůvka Örneği: On İki Düğüm

1367114820932181519105171116412ABCDEFGHIJKL

Başlangıç: her düğüm ayrı bir bileşen (12 bileşen).

1367114820932181519105171116412ABCDEFGHIJKL
BileşenEn ucuz
{A}AC 6
{B}BD 1
{C}AC 6
{D}BD 1
{E}EF 2
{F}EF 2
{G}GI 5
{H}GH 15
{I}GI 5
{J}JL 4
{K}GK 10
{L}JL 4

Tur 1: her bileşenin en ucuz dış kenarı (mavi).

1367114820932181519105171116412ABCDEFGHIJKL

Tur 1 sonu: 7 farklı kenar eklendi (AC, BD, EF, GI, GH, JL, GK), 5 bileşen kaldı: {G, H, I, K} {A, C} {B, D} {E, F} {J, L}. Toplam 43.

1367114820932181519105171116412ABCDEFGHIJKL
BileşenEn ucuz
{A,C}BC 7
{B,D}DF 3
{E,F}DF 3
{G,H,I,K}KL 12
{J,L}KL 12

Tur 2: her bileşenin en ucuz dış kenarı (mavi).

1367114820932181519105171116412ABCDEFGHIJKL

Tur 2 sonu: 3 farklı kenar eklendi (BC, DF, KL), 2 bileşen kaldı: {A, B, C, D, E, F} {G, H, I, J, K, L}. Toplam 65.

1367114820932181519105171116412ABCDEFGHIJKL
BileşenEn ucuz
{A,B,C,D,E,F}EJ 18
{G,H,I,J,K,L}EJ 18

Tur 3: her bileşenin en ucuz dış kenarı (mavi).

1367114820932181519105171116412ABCDEFGHIJKL

Tur 3 sonu: 1 farklı kenar eklendi (EJ), 1 bileşen kaldı: {A, B, C, D, E, F, G, H, I, J, K, L}. MST = 83, yalnızca 3 turda.

Borůvka

Borůvka: Java Kodu ve Karmaşıklık

while (bilesenSayisi > 1) {
  Kenar[] enUcuz = new Kenar[V];
  for (Kenar e : kenarlar) {        // 1) en ucuzlar
    int k1 = bul(ata, e.u), k2 = bul(ata, e.v);
    if (k1 == k2) continue;         // aynı bileşen
    if (enUcuz[k1] == null || e.w < enUcuz[k1].w)
      enUcuz[k1] = e;
    if (enUcuz[k2] == null || e.w < enUcuz[k2].w)
      enUcuz[k2] = e;
  }
  for (Kenar e : enUcuz) {          // 2) hepsini ekle
    if (e == null) continue;
    int k1 = bul(ata, e.u), k2 = bul(ata, e.v);
    if (k1 == k2) continue;         // zaten eklendi
    agac.add(e);
    ata[k1] = k2;                   // birleştir
    bilesenSayisi--;
  }
}
  • Her turda her bileşen en az bir başka bileşenle birleşir → bileşen sayısı en az yarıya iner.
  • Tur sayısı ≤ ⌈log₂ V⌉; her tur tüm kenarları bir kez tarar: O(E).
  • Toplam: O(E log V). Sıralama yapılmaz; "ağırlık sıralaması" gerekmez.
  • e.w < karşılaştırması eşitlikte ilk (küçük indisli) kenarı tutar: bu tutarlı eşitlik bozucu döngüyü önler.

Ters Silme

Ters Silme (Reverse-Delete) Algoritması

  • Minimum kapsayan ağacı bulan açgözlü bir algoritmadır (Kruskal, 1956 makalesinde önerdi).
  • Kenarları ağırlıklarına göre azalan şekilde sıralar.
  • En ağır kenardan başlayarak, çizgenin bağlılığını bozmayan her kenarı siler.
  • Döngü özelliğine dayanır: silinen kenar, bir döngünün en ağır kenarıdır.
Kruskal'ın aynasıKruskal küçük kenarları eklerken, ters silme büyük kenarları silmeye çalışır. Biri boş çizgeden, öteki tam çizgeden başlar.
KullanımDaha çok teorik/öğretici değeri vardır; her silmede bağlılık testi gerektiği için pratikte genellikle yavaştır.

Ters Silme

Ters Silme: Adımlar, Sözde Kod, Karmaşıklık

  1. Tüm kenarları ağırlığına göre azalan şekilde sırala.
  2. Sıradaki en ağır kenarı sil.
  3. Çizge artık bağlı değilse silinen kenarı geri ekle.
  4. Tüm kenarlar işlenene kadar 2. ve 3. adımları tekrarla.
Karmaşıklık: her kenar için bir BFS/DFS (ya da union-find ile yeniden kurma) → O(E · (V + E)). Sıralamanın O(E log E) maliyeti bunun yanında küçük kalır.
TERS_SİLME(G):
  MST = tüm kenarlar
  kenarlar.sırala(azalana göre)
  her bir (u, v, ağırlık) için kenarlar içinde:
    MST.sil((u, v, ağırlık))
    ayrikKume.sıfırla()
    her bir (x, y) için MST içinde:
      ayrikKume.birleştir(x, y)
    kök = ayrikKume.bul(V[0])
    eğer bir v için ayrikKume.bul(v) ≠ kök:
      MST.ekle((u, v, ağırlık))  // geri koy
  döndür MST

Bağlılık testi tüm düğümlere bakar; kökten kopuk en az bir düğüm varsa silinen kenar bir kez geri konur.

Ters Silme

Ters Silme Adım Adım: Yedi Düğüm

58911871596752465130
KenarwDurum
3–415
5–611
1–39
4–69
1–28
4–58
1–47
0–17
3–56
2–45
0–35

Kenarlar azalan sırada: 15, 11, 9, 9, 8, 8, 7, 7, 6, 5, 5. Toplam ağırlık 90.

58911871596752465130
KenarwDurum
3–415silindi
5–611
1–39
4–69
1–28
4–58
1–47
0–17
3–56
2–45
0–35

4–3 = 15 silinir: çizge hâlâ bağlı (kenar bir döngünün en ağırıdır).

58911871596752465130
KenarwDurum
3–415silindi
5–611silindi
1–39
4–69
1–28
4–58
1–47
0–17
3–56
2–45
0–35

6–5 = 11 silinir: çizge hâlâ bağlı (kenar bir döngünün en ağırıdır).

58911871596752465130
KenarwDurum
3–415silindi
5–611silindi
1–39silindi
4–69
1–28
4–58
1–47
0–17
3–56
2–45
0–35

1–3 = 9 silinir: çizge hâlâ bağlı (kenar bir döngünün en ağırıdır).

58911871596752465130
KenarwDurum
3–415silindi
5–611silindi
1–39silindi
4–69kaldı
1–28
4–58
1–47
0–17
3–56
2–45
0–35

4–6 = 9 silinirse düğüm 6 yalnız kalır → bağlılık bozulur, kenar geri eklenir.

58911871596752465130
KenarwDurum
3–415silindi
5–611silindi
1–39silindi
4–69kaldı
1–28silindi
4–58
1–47
0–17
3–56
2–45
0–35

2–1 = 8 silinir: çizge hâlâ bağlı (kenar bir döngünün en ağırıdır).

58911871596752465130
KenarwDurum
3–415silindi
5–611silindi
1–39silindi
4–69kaldı
1–28silindi
4–58silindi
1–47
0–17
3–56
2–45
0–35

4–5 = 8 silinir: çizge hâlâ bağlı (kenar bir döngünün en ağırıdır).

58911871596752465130
KenarwDurum
3–415silindi
5–611silindi
1–39silindi
4–69kaldı
1–28silindi
4–58silindi
1–47kaldı
0–17kaldı
3–56kaldı
2–45kaldı
0–35kaldı

Kalan 6 kenar (7, 7, 6, 5, 5 ve 9) birer köprüdür: hiçbiri silinemez. 6 = V − 1 kenar, MST = 39.

Ters Silme · Kodu adım adım çalıştır

Ters Silme: Kodu Adım Adım İzle

7589751568911ABCDEFG

Kenarlar azalan sıralanır: DE 15, FG 11, BD 9, EG 9, BC 8, EF 8, AB 7, BE 7, DF 6, AD 5, CE 5.

7589751568911ABCDEFG

En yüksek ağırlıklı DE incelenir: DE = 15 silindi, bagliMi = true → silinmiş kalır.

7589751568911ABCDEFG

FG çıkarılırsa bağlılık bozuluyor mu? FG = 11 silindi, bagliMi = true → silinmiş kalır.

7589751568911ABCDEFG

Bir sonraki en ağır kenar BD: BD = 9 silindi, bagliMi = true → silinmiş kalır.

7589751568911ABCDEFG

EG = 9 silinirse G yalnız kalır (FG zaten silindi) → bagliMi = false, EG geri konur; i = 1.

7589751568911ABCDEFG

BC = 8 silindi, bagliMi = true → silinmiş kalır.

7589751568911ABCDEFG

EF = 8 silindi, bagliMi = true → silinmiş kalır.

7589751568911ABCDEFG

AB = 7 silinirse {A, D, F} kopar → geri konur, i = 2.

7589751568911ABCDEFG

BE = 7 silinirse {C, E, G} kopar → geri konur, i = 3.

7589751568911ABCDEFG

DF = 6 silinirse {F} kopar → geri konur, i = 4.

7589751568911ABCDEFG

AD = 5 silinirse {D, F} kopar → geri konur, i = 5.

7589751568911ABCDEFG

CE = 5 silinirse {C} kopar → geri konur, i = 6.

7589751568911ABCDEFG

i = boyut = 6: döngü biter. Silinecek başka kenar yok; kalan ağaç AB, AD, BE, CE, DF, EG → w = 39.

void tersSil(int V, List<Kenar> ke) {
  ke.sort((a, b) -> b.w - a.w); // azalan
  int i = 0;
  while (i < ke.size()) {
    Kenar e = ke.remove(i);     // geçici sil
    if (!bagliMi(V, ke)) {
      ke.add(i, e);             // geri koy
      i++;
    }
  }
}

Karşılaştırma

Dört Algoritmanın Karşılaştırması

KruskalPrimBorůvkaTers silme
Bakışkenar odaklıdüğüm odaklıbileşen odaklıkenar odaklı (silme)
Ara durumormantek ağaçormanbağlı çizge
Dayandığı özellikkesmekesmekesmedöngü
Veri yapısısıralı kenarlar + union-findöncelik kuyruğu / diziunion-findBFS/DFS
ZamanO(E log E)O(V²) ya da O((V + E) log V)O(E log V)O(E · (V + E))
En uygunseyrek çizgeyoğun çizgeparalel / dağıtıköğretim, teori
Bağlı olmayan çizgeorman verirbir bileşenorman verirbileşenleri korur
Dokuz düğümlü çizgede Kruskal ve Prim aynı ağacı (29) bulur; ekleme sırası farklıdır: Kruskal 1, 1, 2, 3, 4, 5, 6, 7 — Prim 4, 7, 1, 1, 2, 3, 6, 5.

Özet

Özet

KonuHatırlanacaklar
MSTbağlı, yönsüz, ağırlıklı çizgede toplam ağırlığı en küçük kapsayan ağaç; V − 1 kenar
Özelliklerkesmenin en hafif kenarı güvenli; döngünün en ağır kenarı dışarıda; farklı ağırlıklar → tek MST
Kruskalkenarları sırala; bul(u) ≠ bul(v) ise ekle ve birleştir — O(E log E)
Union-Findata[] ormanı; yol sıkıştırma + rütbe → işlem başına O(α(V))
Primtek ağacı büyüt; anahtar = ağaca en ucuz kenar — O(V²) / O((V + E) log V)
Borůvkaher bileşen en ucuz dış kenarını aynı anda ekler; ≤ log₂ V tur — O(E log V)
Ters silmeazalan sırada sil, bağlılık bozulursa geri koy — O(E · (V + E))

Özet

Etkileşimli Simülatörler

Minimum Kapsayan Ağaç2–15 düğümlü rastgele, bağlı ve ağırlıklı bir çizge üretin; düğümleri sürükleyerek yerleştirin. Prim (düğüm 0'dan) ve Kruskal'ı adım adım çalıştırın: eklenen ve döngü yüzünden atlanan kenarlar günlükte listelenir, sonunda toplam ağırlık gösterilir.
Önerilen deneylerAynı çizgede iki algoritmayı ardışık çalıştırıp toplam ağırlığın aynı, ekleme sırasının farklı olduğunu görün. Ağırlıkları eşit kenarlar olduğunda iki ağacın farklılaşıp farklılaşmadığını gözlemleyin.

Özet

Sık Yapılan Hatalar

MST'yi en kısa yol ağacı sanmakMST toplam ağırlığı küçültür; iki düğüm arasındaki MST yolu en kısa yol olmak zorunda değildir.
Döngüyü komşulukla denetlemekKruskal'da "u ile v doğrudan bağlı mı?" yetmez; aynı bileşende mi sorusu (bul) sorulmalıdır.
Prim'de uzaklık toplamakanahtar[u] + w yazmak Dijkstra'dır. Prim'de anahtar yalnızca tek kenarın ağırlığıdır.
Negatif ağırlıktan korkmakMST algoritmaları negatif ağırlıkla da doğru çalışır (yalnızca karşılaştırma yapılır); sorun Dijkstra'ya özgüdür.
Bağlı olmayan çizgeMST yoktur, minimum kapsayan orman vardır. while (agac.size() < V − 1) kenarlar bitince dizi sınırını aşar.
Yönlü çizgeye uygulamakBu algoritmalar yönsüz çizge içindir. Yönlü karşılığı (en küçük kapsayan dallanma) Chu–Liu/Edmonds algoritmasıdır.

Özet

Örnek Problemler

Çizge: AB = 2, AC = 3, BC = 1, BD = 4, CD = 5, CE = 6, DE = 7 (yönsüz).

  1. Kruskal'ın incelediği kenarları sırasıyla yazın; hangileri reddedilir? w(T) = ?
  2. Prim'i A'dan çalıştırın: düğümler hangi sırayla ağaca girer? İlk adımdan sonra anahtar dizisi nedir?
  3. Borůvka kaç turda biter? Tur 1'de hangi kenarlar seçilir?
  4. Ters silme hangi kenarları siler?
  5. 100 düğümlü bağlı bir çizgenin MST'sinde kaç kenar vardır?
  6. Tüm ağırlıklara 5 eklenirse MST değişir mi? Toplam ne olur?
Cevapları göster
  1. BC 1 ✓, AB 2 ✓, AC 3 ✗ (döngü), BD 4 ✓, CD 5 ✗, CE 6 ✓ → 4 kenar, w(T) = 13. DE incelenmez.
  2. A, B (2), C (1, B üzerinden), D (4), E (6). A'dan sonra: anahtar[B] = 2, [C] = 3, [D] = [E] = ∞.
  3. 1 tur: A→AB, B→BC, C→BC, D→BD, E→CE; dört farklı kenar tek bileşen yapar.
  4. DE 7 silinir, CE 6 kalır (E kopar), CD 5 silinir, BD 4 kalır, AC 3 silinir, AB ve BC kalır.
  5. V − 1 = 99.
  6. Değişmez: kenarların sırası korunur. Toplam 13 + 4 · 5 = 33 olur.

Özet

Alıştırmalar

  1. Tüm ağırlıklar farklıysa MST'nin tek olduğunu kesme özelliğiyle gösterin.
  2. En büyük kapsayan ağacı bulmak için Kruskal'ı nasıl değiştirirsiniz?
  3. Dokuz düğümlü örneğin MST'sini kullanarak düğümleri 3 kümeye ayırın.
  4. 0..5, ata[bul(x)] = bul(y): birleştir (0,1), (2,3), (1,3), (4,5), (3,5). Son ata? bul(0) neyi değiştirir?
  5. V = 1000: Prim O(V²) ve O(E log V) sürümlerini E = 5 000 ve 500 000 için karşılaştırın.
  6. Kruskal'ı bağlı olmayan çizgede orman döndürecek biçimde düzeltin.
Cevaplar / ipuçları
  1. Her MST kenarı e, T − e'nin tanımladığı kesmenin tek en hafif kenarıdır; o kenar her MST'de olmak zorunda → MST'ler aynı.
  2. Kenarları azalan sıralayın (ya da −w kullanın).
  3. MST'den en ağır 2 kenarı (AC 7, DG 6) silin: {C, D, E, F, H} {A, B} {G, I}.
  4. ata = [1, 3, 3, 5, 5, 5]. bul(0): 0→1→3→5 yolu sıkışır → ata = [5, 5, 3, 5, 5, 5].
  5. V² = 10⁶; E log V ≈ 5 · 10⁴ (yığın kazanır) ve ≈ 5 · 10⁶ (matris kazanır).
  6. Koşul: k < ke.size() && agac.size() < V − 1; sonda agac.size() < V − 1 ise çizge bağlı değildir.

Özet

Kaynaklar

  • Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, MIT Press, 2022 (Bölüm 19: ayrık kümeler, Bölüm 21: MST).
  • Sedgewick ve Wayne, Algorithms, 4. baskı, Addison-Wesley, 2011 (Bölüm 4.3: Minimum Spanning Trees).
  • J. B. Kruskal, "On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem", Proc. AMS 7(1), 1956.
  • R. C. Prim, "Shortest Connection Networks and Some Generalizations", Bell System Technical Journal 36(6), 1957.
  • O. Borůvka, "O jistém problému minimálním", Práce Moravské přírodovědecké společnosti 3, 1926.
  • R. E. Tarjan, "Efficiency of a Good But Not Linear Set Union Algorithm", Journal of the ACM 22(2), 1975.

Son

Bölüm 4.3: Minimum Kapsayan Ağaç Algoritmaları
Sonraki bölüm: Bölüm 4.4: Ağ Akışı
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.