🔗 10.1: Union-Find Veri Yapısı

Dinamik Bağlantı Problemi (Dynamic Connectivity)

📌 Dinamik Bağlantı Problemi

Bir dizi nesne verildiğinde, iki nesnenin bağlı olup olmadığını verimli bir şekilde sorgulamamız ve yeni bağlantılar eklememiz gerekiyor.

Bu basit görünen problem, bilgisayar biliminin en temel ve en zarif veri yapılarından birini ortaya çıkarmıştır: Union-Find (Disjoint Set Union).

📚 Bu Bölümde Öğrenecekleriniz

10.1
Problem Tanımı ve API
10.2
Quick-Find
10.3
Quick-Union
10.4
Weighted QU
10.5
Path Compression
10.6
Uygulamalar

🎯 Problem Tanımı

Dinamik Bağlantı (Dynamic Connectivity)

Girdi: N adet nesne (0'dan N-1'e kadar numaralandırılmış)

İşlemler:

  • Union(p, q): p ve q arasına bağlantı ekle
  • Connected(p, q): p ve q (doğrudan veya dolaylı) bağlı mı?

💡 "Bağlı" Ne Demek?

İki nesne bağlıdır eğer aralarında bir bağlantı zinciri varsa.

Örnek: A-B ve B-C bağlı ise, A ve C de (dolaylı olarak) bağlıdır.

🖥️ Örnek: Bilgisayar Ağı

10 bilgisayardan oluşan bir ağ düşünelim:

Başlangıç: Her bilgisayar ayrı (10 ayrı küme) 0 1 2 3 4 5 6 7 8 9 ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ İşlemler: ────────────────────────────────────────────────── union(4, 3) → 3 ve 4 bağlandı union(3, 8) → 8 de aynı kümeye katıldı union(6, 5) → 5 ve 6 bağlandı union(9, 4) → 9 da {3,4,8} kümesine katıldı union(2, 1) → 1 ve 2 bağlandı Şu anki durum: ○ ○───○ ○───○ ○ 0 1 2 5 6 7 ○───○───○───○ 3 4 8 9 Sorgular: ────────────────────────────────────────────────── connected(0, 7)? → false (farklı kümelerde) connected(8, 9)? → true (aynı kümede) union(5, 0) → {0} ve {5,6} birleşti union(7, 2) → {7} ve {1,2} birleşti union(6, 1) → {0,5,6} ve {1,2,7} birleşti! connected(0, 7)? → true (artık aynı kümede!)

📐 Bağlantı İlişkisinin Matematiksel Özellikleri

"Bağlı olma" ilişkisi matematiksel olarak bir eşdeğerlik ilişkisidir:

1. Dönüşlülük (Reflexive) p, p'ye bağlıdır
2. Simetriklik (Symmetric) p, q'ya bağlı ise → q, p'ye bağlıdır
3. Geçişlilik (Transitive) p-q bağlı ve q-r bağlı ise → p-r bağlıdır

🔑 Bağlı Bileşenler (Connected Components)

Bu özellikler sayesinde nesneler ayrık kümelere (disjoint sets) ayrılır.

Her kümedeki tüm elemanlar birbirine bağlıdır, farklı kümelerdeki elemanlar ise bağlı değildir.

🔧 Union-Find API

Veri yapımızın sağlaması gereken temel arayüz:

Metod Açıklama
UnionFind(n) N nesne ile boş bir Union-Find yapısı oluştur (başlangıçta N ayrı küme)
union(p, q) p ve q'nun bulunduğu kümeleri birleştir
find(p) p'nin ait olduğu kümenin temsilcisini (identifier) döndür
connected(p, q) p ve q aynı kümede mi? (find(p) == find(q))
count() Toplam kaç ayrı küme var?
Union-Find API Şablonu
class UnionFind:
    """
    Union-Find (Disjoint Set Union) veri yapısı.
    
    Dinamik bağlantı problemini çözmek için kullanılır.
    """
    
    def __init__(self, n: int):
        """
        N nesne ile yeni bir Union-Find yapısı oluşturur.
        Başlangıçta her nesne kendi kümesindedir (N ayrı küme).
        
        Args:
            n: Nesne sayısı (0'dan n-1'e kadar numaralandırılmış)
        """
        pass
    
    def union(self, p: int, q: int) -> None:
        """
        p ve q'nun bulunduğu kümeleri birleştirir.
        
        Args:
            p: Birinci nesne
            q: İkinci nesne
        """
        pass
    
    def find(self, p: int) -> int:
        """
        p'nin ait olduğu kümenin temsilcisini döndürür.
        
        Aynı kümedeki tüm elemanlar için aynı değeri döndürür.
        
        Args:
            p: Sorgulanacak nesne
            
        Returns:
            Kümenin temsilci ID'si
        """
        pass
    
    def connected(self, p: int, q: int) -> bool:
        """
        p ve q'nun aynı kümede olup olmadığını kontrol eder.
        
        Args:
            p: Birinci nesne
            q: İkinci nesne
            
        Returns:
            True eğer aynı kümedeler, False aksi halde
        """
        return self.find(p) == self.find(q)
    
    def count(self) -> int:
        """
        Mevcut ayrık küme sayısını döndürür.
        
        Returns:
            Küme sayısı
        """
        pass

🌍 Nerede Kullanılır?

🖥️ Bilgisayar Ağları

İki bilgisayar birbirine bağlı mı? Hangi bilgisayarlar aynı ağda?

Union: Kablo çek
Connected: Paket gönderilebilir mi?

👥 Sosyal Ağlar

İki kişi arkadaş zinciri ile bağlı mı? Kaç farklı topluluk var?

Union: Arkadaşlık kur
Connected: Aynı grupta mı?

🖼️ Görüntü İşleme

Benzer pikselleri grupla. Görüntüdeki farklı nesneleri ayır.

Union: Benzer pikselleri birleştir
Connected: Aynı nesne mi?

🌲 Kruskal MST

Minimum Spanning Tree algoritmasında döngü kontrolü.

Union: Kenar ekle
Connected: Döngü oluşur mu?

🎮 Percolation

Su veya elektrik yukarıdan aşağıya akabilir mi?

Union: Hücre aç
Connected: Yol var mı?

🧬 Hesaplamalı Biyoloji

Protein etkileşim ağları, gen aileleri.

Union: Etkileşim tespit et
Connected: İlişkili mi?

📈 Algoritma Gelişim Tarihi

Bu bölümde, basit ama yavaş çözümlerden başlayarak, çok hızlı bir algoritmaya nasıl ulaşıldığını göreceğiz:

Quick-Find

Find işlemi hızlı (O(1)), ama Union yavaş (O(N))

Problem: Her union N eleman günceller

Quick-Union

Union işlemi basit, ama ağaç çok uzun olabilir

Problem: Find en kötü O(N)

Weighted Quick-Union

Küçük ağacı büyüğe bağla → Ağaç yüksekliği O(log N)

İyileşme: Her işlem O(log N)

Path Compression

Find sırasında ağacı düzleştir → Neredeyse sabit süre

Sonuç: Amortize O(α(N)) ≈ O(1)

🏆 Sonuç

Basit bir problemle başladık, ama doğru iyileştirmelerle neredeyse doğrusal bir algoritma elde ettik!

N nesne üzerinde M işlem: Naif O(MN) → Optimize O(M × α(N))

🎯 Bölüm Hedefi

Bu bölümün sonunda şunları yapabileceksiniz:

  • Dinamik bağlantı problemini anlama
  • 4 farklı Union-Find implementasyonunu kodlama
  • Her birinin karmaşıklığını analiz etme
  • Neden son versiyonun bu kadar hızlı olduğunu açıklama
  • Graf algoritmalarında (özellikle Kruskal MST) kullanma

Hazırsanız, Quick-Find algoritmasıyla başlayalım! 🚀