Bölüm 8: Rastgele Algoritmalar
Giriş
Öğrenme Çıktıları
Rastgele algoritmanın tanımını, beklenen çalışma süresini ve Las Vegas / Monte Carlo ayrımını açıklamak.
Fisher–Yates karıştırmasını yazmak, saf karıştırmanın neden yanlı olduğunu göstermek; BogoSort'un beklenen Θ(n · n!) süresini hesaplamak.
Rastgele pivotlu bölmeyi adım adım izlemek; beklenen O(n log n) ve en kötü O(n²) süreyi gerekçelendirmek.
π tahmini, Miller–Rabin asallık testi ve Karger min-kesit algoritmasında hata olasılığını hesaplamak ve tekrarla küçültmek.
Giriş
Şanslı Algoritmalar
- Bazen problem çözmede şans oyunlarına benzer teknikler kullanılır.
- Algoritma, karar verme sürecinde rastgelelikten (şans) yararlanır: yazı-tura atar, zar atar, rastgele bir eleman seçer.
- Örnek oyun: iki zar atılır; toplam 7 ya da 11 ise oyuncu kazanır.
Giriş
Rastgele Algoritmalar
- Rastgele algoritma (randomized algorithm): girdiye ek olarak rastgele sayılar kullanarak çalışır.
- Aynı girdiyle iki çalıştırma farklı adımlar izleyebilir: çalışma süresi (ve bazen çıktı) her çalıştırmada değişebilir.
- Süre artık bir rastgele değişkendir: beklenen süre E[T(n)] incelenir. Beklenen değer algoritmanın kendi yazı-turaları üzerinden alınır, girdi üzerinden değil.
Giriş
Neden Rastgelelik?
Deterministik QuickSort sıralı dizide O(n²) olur. Rastgele pivotta hiçbir girdi sürekli kötü değildir: kötü durum yalnızca şanssız yazı-turalarla oluşur.
Rastgele algoritma çoğu zaman en iyi deterministik algoritmadan çok daha kısa ve anlaşılırdır (Karger min-kesit, rastgele QuickSelect).
Miller–Rabin, yüzlerce basamaklı sayıların asallığını milisaniyeler içinde, çok küçük bir hata olasılığıyla belirler.
Monte Carlo benzetimleri, rastgele örneklem ve dağıtık sistemlerde lider seçimi gibi işler rastgelelik olmadan zordur.
Bedel: süre ya da doğruluk artık olasılıksal bir garantidir; iyi bir rastgele sayı üreteci gerekir.
Giriş
Olasılık Hatırlatması
| Kavram | Tanım / kural | Örnek |
|---|---|---|
| Beklenen değer | E[X] = Σ x · P(X = x) | bir zarın beklenen değeri 3,5 |
| Doğrusallık | E[X + Y] = E[X] + E[Y] (bağımsızlık gerekmez) | iki zarın toplamı: 7 |
| Gösterge değişkeni | XA = 1 (A olursa), 0 → E[XA] = P(A) | QuickSort'ta "i ile j karşılaştırıldı mı?" |
| Geometrik dağılım | başarı olasılığı p olan denemeler: ilk başarıya kadar beklenen deneme 1/p | BogoSort: p = 1/n! → n! karıştırma |
| Bağımsız tekrar | her biri p ile başarısız k bağımsız deneme: hepsi başarısız pk | Miller–Rabin: (1/4)k |
| Markov eşitsizliği | X ≥ 0 ise P(X ≥ c · E[X]) ≤ 1/c | Las Vegas → Monte Carlo |
Algoritma Türleri
Las Vegas ve Monte Carlo
| Las Vegas | Monte Carlo | |
|---|---|---|
| Doğruluk | Her zaman doğru sonuç | Küçük bir olasılıkla yanlış sonuç |
| Süre | Rastgele; beklenen süre analiz edilir | Sınırlı (deterministik üst sınır) |
| Rastgele olan | ne kadar süreceği | sonucun doğru olup olmadığı |
| Örnekler | Rastgele QuickSort, QuickSelect, BogoSort, Fisher–Yates | Miller–Rabin, Karger min-kesit, π tahmini |
Miller–Rabin "bileşik" derse kesin doğrudur; yalnızca "asal" yanıtı yanlış olabilir.
π tahmini gibi sayısal benzetimler her iki yönde de sapabilir; hata örnek sayısıyla küçülür.
Algoritma Türleri
Hata Olasılığını Küçültme
Tek turda yanılma olasılığı en çok q ise, k bağımsız tur sonra yanılma ≤ qk.
- Miller–Rabin: q ≤ 1/4 → k = 20 turda ≤ 4−20 ≈ 9 · 10−13.
- Karger: başarı ≥ 2/(n(n−1)); n(n−1)/2 · ln n tekrarla başarısızlık ≤ 1/n.
- Las Vegas → Monte Carlo: algoritmayı 2 · E[T] adım sonra durdur. Markov: P(T ≥ 2 E[T]) ≤ 1/2 → en çok 1/2 olasılıkla "yanıt yok".
- Monte Carlo → Las Vegas: yanıt hızlıca doğrulanabiliyorsa (ör. bulunan çarpanlar çarpılır), doğru çıkana kadar tekrarla. Beklenen tekrar = 1/p.
Karıştırma
Örnek: Karıştırma
- Sıralı bir listenin elemanlarını karıştırmak (shuffle) için rastgelelik kullanılır: kart destesi, rastgele test verisi, şarkı listesi.
- Doğruluk: her elemanın her konumda eşit olasılıkla bulunması; daha güçlüsü, n! permütasyonun her birinin olasılığı 1/n! olmalı.
- Çalışma zamanı: Fisher–Yates her çalıştırmada tam n − 1 takas yapar: Θ(n). Değişen, sürenin değil sonucun kendisidir.
- Java'da hazır:
Collections.shuffle(liste)(Fisher–Yates).
| n | n! permütasyon |
|---|---|
| 3 | 6 |
| 4 | 24 |
| 10 | 3 628 800 |
| 52 | ≈ 8,07 · 1067 |
Karıştırma · Kodu adım adım çalıştır
Fisher–Yates (Knuth) Karıştırması
Başlangıç: a = [1, 2, 3, 4, 5]. Sondan başlayarak her konuma, henüz yerleşmemiş elemanlardan biri rastgele seçilir.
i = 4: a[0..4] arasındaki 5 elemandan biri a[4] konumuna gelecek.
zar.nextInt(5) → j = 1 (olasılık 1/5).
a[4] ↔ a[1] takas → [1, 5, 3, 4, 2]. a[4] = 2 artık kesinleşti (yeşil).
i = 3: a[0..3] arasındaki 4 elemandan biri a[3] konumuna gelecek.
zar.nextInt(4) → j = 3 (j = i: eleman yerinde kalır).
Kendisiyle takas: dizi değişmez; a[3] = 4 kesinleşti.
i = 2: a[0..2] arasındaki 3 elemandan biri a[2] konumuna gelecek.
zar.nextInt(3) → j = 0 (olasılık 1/3).
a[2] ↔ a[0] takas → [3, 5, 1, 4, 2]. a[2] = 1 artık kesinleşti (yeşil).
i = 1: a[0..1] arasındaki 2 elemandan biri a[1] konumuna gelecek.
zar.nextInt(2) → j = 1 (j = i: eleman yerinde kalır).
Kendisiyle takas: dizi değişmez; a[1] = 5 kesinleşti.
Döngü bitti: [3, 5, 1, 4, 2]. Toplam olası çekiliş sayısı 5 · 4 · 3 · 2 = 120 = 5!: her permütasyon tam bir kez → düzgün dağılım.
static void karistir(int[] a) { for (int i = a.length - 1; i > 0; i--) { int j = zar.nextInt(i + 1); // 0 ≤ j ≤ i int t = a[i]; a[i] = a[j]; a[j] = t; } }
Karıştırma
Saf Karıştırma Yanlıdır
// YANLI: her i için 0..n-1 arasından seç for (int i = 0; i < n; i++) { int j = zar.nextInt(n); takas(a, i, j); }
- n çekilişin her biri n değer alır → nn eşit olasılıklı yol.
- n = 3: 33 = 27 yol, 3! = 6 permütasyon. 27, 6'ya bölünmez → permütasyonlar eşit olasılıklı olamaz.
- Sık görülen bu kalıbın doğrusu Fisher–Yates'tir:
nextInt(i + 1).
| sonuç | yol | olasılık | olması gereken |
|---|---|---|---|
123 | 4/27 | 0,148 | 1/6 ≈ 0,167 |
132 | 5/27 | 0,185 | 1/6 ≈ 0,167 |
213 | 5/27 | 0,185 | 1/6 ≈ 0,167 |
231 | 5/27 | 0,185 | 1/6 ≈ 0,167 |
312 | 4/27 | 0,148 | 1/6 ≈ 0,167 |
321 | 4/27 | 0,148 | 1/6 ≈ 0,167 |
[1, 2, 3] dizisinin 27 çekiliş dizisi tek tek sayıldı (Fisher–Yates'te 3 · 2 = 6 yol, her permütasyon 1 kez).
BogoSort
BogoSort
- Sıralama algoritmaları arasında en kötü performansa sahip olanlardan biridir ("aptal sıralama", permutation sort).
- Temel mantık: liste sıralı olana kadar rastgele karıştır.
- Eğlenceli ve öğretici bir Las Vegas algoritmasıdır; gerçek dünyada kullanılmaz.
- Liste sıralı mı? Evet → işlemi tamamla.
- Hayır → listeyi rastgele karıştır, adım 1'e dön.
static void bogoSirala(int[] a) { while (!siraliMi(a)) karistir(a); // Fisher–Yates } static boolean siraliMi(int[] a) { for (int i = 0; i + 1 < a.length; i++) if (a[i] > a[i + 1]) return false; return true; }
BogoSort
BogoSort Örneği: [5, 2, 8, 4]
[5, 2, 8, 4] listesi; her karıştırma Fisher–Yates ile (tohumlu bir çalıştırma). Kırmızı: ilk ters sıralı komşu çift.
Başlangıç [5, 2, 8, 4]: a[0] = 5 > a[1] = 2 → sıralı değil, karıştırmaya başla.
Karıştırma 1: [5, 4, 2, 8] → a[0] = 5 > a[1] = 4, sıralı değil.
Karıştırma 2: [8, 4, 5, 2] → a[0] = 8 > a[1] = 4, sıralı değil.
Karıştırma 3: [4, 2, 8, 5] → a[0] = 4 > a[1] = 2, sıralı değil.
Karıştırma 4: [2, 8, 4, 5] → a[1] = 8 > a[2] = 4, sıralı değil.
Karıştırma 5: [5, 8, 2, 4] → a[1] = 8 > a[2] = 2, sıralı değil.
Karıştırma 6: [8, 4, 2, 5] → a[0] = 8 > a[1] = 4, sıralı değil.
Karıştırma 7: [2, 8, 5, 4] → a[1] = 8 > a[2] = 5, sıralı değil.
Karıştırma 8: [2, 4, 5, 8] → sıralı! Algoritma durur. Bu çalıştırmada 8 karıştırma gerekti; beklenen değer 4! = 24.
BogoSort
BogoSort Analizi
- n farklı eleman: rastgele bir karıştırmanın sıralı çıkma olasılığı p = 1/n!.
- Denemeler bağımsız → geometrik dağılım: beklenen karıştırma sayısı 1/p = n!.
- Her tur: karıştırma O(n) + kontrol O(n) → beklenen süre Θ(n · n!). Bu, O((n + 1)!) ile aynı büyüklüktedir, çünkü (n + 1)! = (n + 1) · n!.
- En iyi durum: dizi zaten sıralı → tek kontrol, O(n).
- En kötü durum: sınırsız. Şanssız karıştırmalar sonsuza dek sürebilir (olasılığı 0'a gider). O((n + 1)!) yalnızca beklenen süre için bir sınırdır, en kötü durum için değil.
| n | beklenen karıştırma n! | süre (10⁹ karıştırma/s) |
|---|---|---|
| 5 | 120 | 0,12 µs |
| 10 | 3 628 800 | 3,6 ms |
| 12 | 479 001 600 | 0,48 s |
| 13 | 6 227 020 800 | 6,2 s |
| 15 | 1 307 674 368 000 | ≈ 22 dakika |
| 20 | 2 432 902 008 176 640 000 | ≈ 77 yıl |
Rastgele QuickSort
QuickSort Algoritması
- Böl ve fethet (divide and conquer) ile çalışan, yerinde (in-place) hızlı bir sıralama algoritmasıdır (Hoare, 1962).
- Temel mantık:
- Bir pivot eleman seçilir.
- Bölme (partition): pivottan küçükler soluna, büyükler sağına yerleştirilir; pivot kalıcı yerine oturur.
- Her iki parça için aynı işlem özyinelemeli uygulanır.
- Birleştirme adımı gerekmez: parçalar zaten yerinde sıralanmıştır.
Pivot, alt dizinin elemanları arasından düzgün rastgele seçilir. Algoritma her zaman doğru sonuç verir (Las Vegas); yalnızca süresi pivot seçimlerine bağlıdır.
Rastgele QuickSort
Pivot Seçimi ve Etkisi
| Pivot stratejisi | Kötü girdi | Beklenen / tipik | En kötü |
|---|---|---|---|
| İlk ya da son eleman | sıralı / ters sıralı dizi (çok yaygın!) | O(n log n)* | O(n²) |
| Ortanca-üç (median-of-3) | özel hazırlanmış "killer" diziler | O(n log n)* | O(n²) |
| Rastgele eleman | yok: kötülük yalnızca şanssızlıktan | O(n log n), her girdi için | O(n²) |
| Gerçek ortanca (BFPRT) | yok | O(n log n) | O(n log n) |
- * Deterministik stratejilerde O(n log n) yalnızca girdi rastgele sıralıysa geçerlidir (ortalama durum). Rastgele pivotta ise beklenti algoritmanın kendi seçimleri üzerindendir (beklenen süre).
- İyi pivot seçimi beklenen süreyi iyileştirir, en kötü durumu ortadan kaldırmaz: rastgele pivotta da O(n²) mümkündür, ama olasılığı çok küçüktür.
- BFPRT'nin sabitleri büyüktür; uygulamada rastgele ya da ortanca-üç pivot tercih edilir.
Rastgele QuickSort
QuickSort Adım Adım: [7, 2, 1, 6, 8, 5, 3, 4]
Kök: [7, 2, 1, 6, 8, 5, 3, 4], pivot 4 seçildi.
Bölme sonucu: sol [2, 1, 3] (≤ 4), sağ [8, 5, 7, 6] (> 4). Pivot 4 iki parçaya da girmez, indis 3'te kalıcı yerindedir. Sol parçada pivot 1, sağda 6 seçiliyor.
Pivot 1: sol parça boş (∅), sağ [3, 2]. Pivot 6: sol [5], sağ [7, 8]. Tek elemanlı parçalar zaten sıralıdır (yeşil).
Son düzey: [3, 2] pivot 3 → [2]; [7, 8] pivot 8 → [7]. Yapraklar birleştirilmeden yerinde sıralı dizi oluşur: [1, 2, 3, 4, 5, 6, 7, 8].
Parça içi sıralar Lomuto bölmesine göredir. Pivot, kalıcı yerine oturduğu için parçaların hiçbirine dahil edilmez.
Rastgele QuickSort
Rastgele Pivotlu QuickSort Çalıştırması
[6, 5, 3, 1, 8, 7, 2, 4]; pivotlar rastgele seçildi: 3, 1, 4, 6, 8. Siyah: pivot · kırmızı çerçeve: i ve j işaretçileri · yeşil: kesinleşmiş · soluk: etkin alt dizinin dışı.
Alt dizi a[0..7] = [6, 5, 3, 1, 8, 7, 2, 4]: pivot rastgele seçildi → 3 (indis 2, siyah kutu).
i soldan ilerler, 3'ten küçükleri atlar ve a[0] = 6'da durur; j sağdan ilerler, 3'ten büyükleri atlar ve a[6] = 2'de durur. i < j → takas edilecek.
a[0] ↔ a[6] takas → [2, 5, 3, 1, 8, 7, 6, 4].
i soldan ilerler, 3'ten küçükleri atlar ve a[1] = 5'te durur; j sağdan ilerler, 3'ten büyükleri atlar ve a[3] = 1'de durur. i < j → takas edilecek.
a[1] ↔ a[3] takas → [2, 1, 3, 5, 8, 7, 6, 4].
İşaretçiler karşılaştı (i ≥ j): pivot 3 kalıcı yerinde (indis 2). Solunda yalnızca küçükler, sağında yalnızca büyükler var.
Alt dizi a[0..1] = [2, 1]: pivot rastgele seçildi → 1 (indis 1, siyah kutu).
i soldan ilerler, 1'den küçükleri atlar ve a[0] = 2'de durur; j sağdan ilerler, 1'den büyükleri atlar ve a[1] = 1'de durur. i < j → takas edilecek.
a[0] ↔ a[1] takas → [1, 2, 3, 5, 8, 7, 6, 4]. Pivotun kendisi de yer değiştirebilir; konumu izlenir.
İşaretçiler karşılaştı (i ≥ j): pivot 1 kalıcı yerinde (indis 0). Solunda yalnızca küçükler, sağında yalnızca büyükler var.
Tek elemanlı alt dizi a[1] = 2 zaten sıralı: kesinleşti.
Alt dizi a[3..7] = [5, 8, 7, 6, 4]: pivot rastgele seçildi → 4 (indis 7, siyah kutu).
i soldan ilerler, 4'ten küçükleri atlar ve a[3] = 5'te durur; j sağdan ilerler, 4'ten büyükleri atlar ve a[7] = 4'te durur. i < j → takas edilecek.
a[3] ↔ a[7] takas → [1, 2, 3, 4, 8, 7, 6, 5]. Pivotun kendisi de yer değiştirebilir; konumu izlenir.
İşaretçiler karşılaştı (i ≥ j): pivot 4 kalıcı yerinde (indis 3). Solunda yalnızca küçükler, sağında yalnızca büyükler var.
Alt dizi a[4..7] = [8, 7, 6, 5]: pivot rastgele seçildi → 6 (indis 6, siyah kutu).
i soldan ilerler, 6'dan küçükleri atlar ve a[4] = 8'de durur; j sağdan ilerler, 6'dan büyükleri atlar ve a[7] = 5'te durur. i < j → takas edilecek.
a[4] ↔ a[7] takas → [1, 2, 3, 4, 5, 7, 6, 8].
i soldan ilerler, 6'dan küçükleri atlar ve a[5] = 7'de durur; j sağdan ilerler, 6'dan büyükleri atlar ve a[6] = 6'da durur. i < j → takas edilecek.
a[5] ↔ a[6] takas → [1, 2, 3, 4, 5, 6, 7, 8]. Pivotun kendisi de yer değiştirebilir; konumu izlenir.
İşaretçiler karşılaştı (i ≥ j): pivot 6 kalıcı yerinde (indis 5). Solunda yalnızca küçükler, sağında yalnızca büyükler var.
Tek elemanlı alt dizi a[4] = 5 zaten sıralı: kesinleşti.
Alt dizi a[6..7] = [7, 8]: pivot rastgele seçildi → 8 (indis 7, siyah kutu).
Pivot 8: i, 7'yi atlayıp 8'de durur; j zaten 8'de. i ≥ j → takas yok, 8 kalıcı yerinde (indis 7).
Tek elemanlı alt dizi a[6] = 7 zaten sıralı: kesinleşti. Dizi sıralandı: [1, 2, 3, 4, 5, 6, 7, 8].
Rastgele QuickSort · Kodu adım adım çalıştır
Rastgele Pivotlu Bölme (Lomuto)
zar.nextInt(8) → r = 2: pivot a[2] = 3.
Pivot sona taşınır: a[2] ↔ a[7] → [6, 5, 4, 1, 8, 7, 2, 3].
pivot = 3, k = 0: k, "≤ pivot" bölgesinin bittiği yer.
a[0] = 6 ≤ 3 mü? Hayır → "> pivot" bölgesinde kalır, i ilerler.
a[1] = 5 ≤ 3 mü? Hayır → "> pivot" bölgesinde kalır, i ilerler.
a[2] = 4 ≤ 3 mü? Hayır → "> pivot" bölgesinde kalır, i ilerler.
a[3] = 1 ≤ 3 mü? Evet → k konumuna taşınacak.
a[3] ↔ a[0] takas, k = 1. Yeşil-gri: ≤ 3 bölgesi, açık: > 3 bölgesi.
a[4] = 8 ≤ 3 mü? Hayır → "> pivot" bölgesinde kalır, i ilerler.
a[5] = 7 ≤ 3 mü? Hayır → "> pivot" bölgesinde kalır, i ilerler.
a[6] = 2 ≤ 3 mü? Evet → k konumuna taşınacak.
a[6] ↔ a[1] takas, k = 2. Yeşil-gri: ≤ 3 bölgesi, açık: > 3 bölgesi.
Döngü bitti. Pivot, k = 2 konumuna takas edilir → [1, 2, 3, 6, 8, 7, 5, 4].
return 2: 3 kalıcı yerinde. Sonra hizliSirala(a, 0, 1) ve hizliSirala(a, 3, 7) çağrılır.
static int bol(int[] a, int alt, int ust) { int r = alt + zar.nextInt(ust - alt + 1); takas(a, r, ust); // pivot sona int pivot = a[ust], k = alt; for (int i = alt; i < ust; i++) if (a[i] <= pivot) takas(a, i, k++); // küçükleri sola takas(a, k, ust); // pivot yerine return k; }
Rastgele QuickSort
Rastgele QuickSort: Kod
static Random zar = new Random(); static void hizliSirala(int[] a, int alt, int ust) { if (alt < ust) { int p = bol(a, alt, ust); // rastgele hizliSirala(a, alt, p - 1); hizliSirala(a, p + 1, ust); } }
bol(önceki slayt) rastgele bir indis seçer, pivotu sona taşır ve Lomuto bölmesi uygular.- Tek bir
Randomnesnesi kullanılır; her çağrıdanew Random()oluşturmak gereksiz ve kötü uygulamadır. - Ek bellek: özyineleme yığını; beklenen derinlik O(log n). Küçük parçaya önce inilip büyük parça döngüye çevrilirse en kötü durumda da O(log n).
- Tekrarlı anahtarlar çoksa üç yollu bölme (<, =, >) kullanılır.
Rastgele QuickSort
QuickSort Analizi
| Durum | Yineleme bağıntısı | Süre |
|---|---|---|
| En iyi | T(n) = 2T(n/2) + Θ(n) | Θ(n log n) |
| Beklenen (rastgele pivot) | T(n) = (1/n) Σq [T(q) + T(n−1−q)] + Θ(n) | Θ(n log n) |
| En kötü | T(n) = T(n−1) + Θ(n) | Θ(n²) |
Rastgele pivotta en kötü durumun olasılığı: her adımda en küçük ya da en büyük seçilmeli → 2n−1/n! (n = 20 için ≈ 2 · 10−13).
Rastgele QuickSort
Beklenen Karşılaştırma
- Elemanları sıralı hâlleriyle adlandır: z1 < z2 < … < zn. Gösterge Xij = 1 ⇔ zi ile zj karşılaştırılır.
- İki eleman yalnızca biri pivotken karşılaştırılır. {zi, …, zj} kümesinden ilk seçilen pivot arada bir eleman olursa zi ile zj ayrı parçalara düşer ve hiç karşılaşmaz.
- Bu kümeden ilk pivot düzgün rastgeledir → P(Xij = 1) = 2 / (j − i + 1).
- Doğrusallık: E[X] = Σi<j 2/(j − i + 1) < 2n Hn ≈ 1,39 n log₂ n.
- Kesin değer: E[X] = 2(n + 1)Hn − 4n.
| n | rastgele pivot (beklenen) | sıralı girdi, ilk eleman pivot |
|---|---|---|
| 10 | 24,4 | 45 |
| 100 | 648 | 4 950 |
| 1 000 | 10 986 | 499 500 |
| 106 | 2,48 · 107 | 5,0 · 1011 |
Rastgele QuickSort
Sıralama Algoritmaları Karşılaştırması
| Algoritma | En iyi | Beklenen / ort. | En kötü | Ek bellek | Kararlı |
|---|---|---|---|---|---|
| BubbleSort | O(n) | O(n²) | O(n²) | O(1) | evet |
| MergeSort | O(n log n) | O(n log n) | O(n log n) | O(n) | evet |
| Rastgele QuickSort | O(n log n) | O(n log n) | O(n²) | O(log n) | hayır |
| BogoSort | O(n) | Θ(n · n!) | sınırsız | O(1) | hayır |
- QuickSort, MergeSort'tan daha fazla yer değiştirme yapabilir; ancak yerinde çalıştığı ve önbelleği iyi kullandığı için genellikle daha hızlıdır.
- BubbleSort gibi basit O(n²) algoritmalardan büyük n için çok daha hızlıdır.
- Java'nın
Arrays.sort(int[])yöntemi ilkel türler için çift pivotlu QuickSort kullanır.
Rastgele QuickSort
Rastgele Seçme (QuickSelect)
static int sec(int[] a, int alt, int ust, int s) { if (alt == ust) return a[alt]; int p = bol(a, alt, ust); if (s == p) return a[p]; if (s < p) return sec(a, alt, p - 1, s); return sec(a, p + 1, ust, s); }
- Amaç: dizinin s. en küçük elemanını (ör. ortanca) sıralamadan bulmak.
- Aynı rastgele bölme kullanılır, ama yalnızca tek tarafa inilir.
- Beklenen süre O(n) (ortanca için ≈ 3,39 n karşılaştırma); en kötü O(n²).
- Örnek: [6, 5, 3, 1, 8, 7, 2, 4] için s = 2 (0 tabanlı). Pivot 3 ile bölme p = 2 verir (bkz. bölme izlemesi) → ilk denemede yanıt 3.
Monte Carlo Algoritmaları
Monte Carlo ile π
- Birim kareye düzgün rastgele noktalar at. Çeyrek dairenin alanı π/4, karenin alanı 1 → P(içeride) = π/4, yani π ≈ 4 · iç / n.
- Hata ≈ 1/√n ile azalır: bir basamak daha doğruluk için 100 kat nokta gerekir.
static double piTahmin(int n) { int ic = 0; for (int t = 0; t < n; t++) { double x = zar.nextDouble(), y = zar.nextDouble(); if (x * x + y * y <= 1) ic++; } return 4.0 * ic / n; }
300 nokta: 239 içeride → π ≈ 4 · 239/300 = 3,187.
Monte Carlo Algoritmaları
Deneyin: Monte Carlo π
| nokta sayısı n | 0 |
| içeride | 0 |
| π tahmini | — |
| hata |π̂ − π| | — |
| beklenen hata ≈ 1,64/√n | — |
Yeşil: çeyrek dairenin içinde · kırmızı: dışında. Çizimde ilk 3000 nokta gösterilir, sayım tüm noktalarla sürer. 1,64 = 4 · √(p(1 − p)), p = π/4.
Monte Carlo Algoritmaları
Miller–Rabin Asallık Testi
- Fermat'nın küçük teoremi: n asal ve 1 < a < n ise an−1 ≡ 1 (mod n). Bu eşitlik bozulursa n kesin bileşiktir; ama bazı bileşikler (Carmichael sayıları) her taban için eşitliği sağlar.
- Karekök özelliği: n asal ise x² ≡ 1 (mod n) yalnızca x ≡ ±1 için sağlanır.
- n − 1 = 2s · d (d tek) yazılır; rastgele a için ad, a2d, …, a2s−1d (mod n) dizisine bakılır.
- Dizi 1 ile başlamıyor ve n − 1 hiç görünmüyorsa a, n'nin bileşik olduğunun tanığıdır (witness). Aksi hâlde n bu turu "geçer".
- Bileşik n için tabanların en çok 1/4'ü yalancıdır → k bağımsız turda hata ≤ 4−k. Her tur O(log n) modüler çarpma: toplam O(k log³ n) bit işlemi.
Monte Carlo Algoritmaları
Miller–Rabin: Kod
static boolean asalMi(long n, int k) { if (n < 4) return n == 2 || n == 3; if (n % 2 == 0) return false; long d = n - 1; int s = 0; // n-1 = 2^s·d while (d % 2 == 0) { d /= 2; s++; } for (int tur = 0; tur < k; tur++) { long a = 2 + zar.nextLong(n - 3); // [2, n-2] long x = usMod(a, d, n); // a^d mod n if (x == 1 || x == n - 1) continue; boolean tanik = true; for (int r = 1; r < s && tanik; r++) { x = x * x % n; if (x == n - 1) tanik = false; } if (tanik) return false; // kesin bileşik } return true; // muhtemelen asal }
usMod: hızlı modüler üs alma (kare al-çarp), O(log d) çarpma.- Taban a, [2, n − 2] aralığından düzgün seçilir.
longilex * xyalnızca n < 3 · 109 için taşmaz; daha büyük n içinBigInteger.modPowya daisProbablePrime.
Monte Carlo Algoritmaları
Miller–Rabin Örnekleri
| n | n − 1 | a | ad, a2d, … (mod n) | sonuç |
|---|---|---|---|---|
| 61 | 22 · 15 | 2 | 11, 60 | geçti (asal olabilir) |
| 221 | 22 · 55 | 174 | 47, 220 | geçti (asal olabilir) |
| 221 | 22 · 55 | 137 | 188, 205 | bileşik (a tanık) |
| 561 | 24 · 35 | 2 | 263, 166, 67, 1 | bileşik (a tanık) |
- 61 asaldır: dizi n − 1 = 60'a ulaşır.
- 221 = 13 · 17: a = 174 bir güçlü yalancıdır (dizi 220'ye ulaşır); a = 137 ise tanıktır. Bu yüzden birden çok tur gerekir.
- 561 = 3 · 11 · 17 bir Carmichael sayısıdır: 2560 ≡ 1, yani Fermat testi aldanır. Miller–Rabin ise 67² ≡ 1 olduğunu görür: 67, 1'in ±1 dışında bir karekökü → bileşik.
Monte Carlo Algoritmaları
Karger Min-Kesit Algoritması
Başlangıç: 6 düğüm, 8 kenar. Minimum kesit 2'dir (ör. {3, 4} | geri kalanı). Koyu düğüm: son büzmede oluşan süper düğüm.
Rastgele kenar (0, 2) büzüldü: uçları tek süper düğümde birleşti, aradaki kenarlar (öz-döngüler) silindi, paralel kenarlar (×k) korunur. Kalan: 7 kenar.
Rastgele kenar (1, 5) büzüldü: uçları tek süper düğümde birleşti, aradaki kenarlar (öz-döngüler) silindi, paralel kenarlar (×k) korunur. Kalan: 6 kenar.
Rastgele kenar (3, 4) büzüldü: uçları tek süper düğümde birleşti, aradaki kenarlar (öz-döngüler) silindi, paralel kenarlar (×k) korunur. Kalan: 5 kenar.
Rastgele kenar (0, 1) büzüldü: uçları tek süper düğümde birleşti, aradaki kenarlar (öz-döngüler) silindi, paralel kenarlar (×k) korunur. Kalan: 2 kenar. İki süper düğüm kaldı → bulunan kesit = 2 (minimum, başarılı çalıştırma).
- Problem: çizgeyi iki parçaya ayıran en az kenarlı kesit (global min-cut).
- Algoritma: 2 düğüm kalana dek düzgün rastgele bir kenarı büz; kalan kenar sayısı bir kesittir.
- Bir çalıştırma minimum kesiti en az 2/(n(n−1)) olasılıkla bulur (n = 6: ≥ 1/15). Bu çizgede 200 000 benzetimde gözlenen ≈ 0,46.
- Çıktı yanlış (daha büyük kesit) olabilir → Monte Carlo. Ör. ilk kenarlar (1,2), (4,5), (3,4), (0,1) seçilirse {0,1,2} | {3,4,5} kesiti, 3 kenar.
- n(n−1)/2 · ln n tekrar → başarısızlık ≤ 1/n; toplam O(n4 log n) (basit uygulama).
Monte Carlo Algoritmaları
Diğer Uygulamalar
Rastgele zamanlama (iş atama), benzetilmiş tavlama ve genetik algoritmalar da rastgeleliği arama için kullanır (sonraki slayt).
Monte Carlo Algoritmaları
Rastgele Arama Sezgiselleri
- Rastgele bir komşu çözüm üret; daha iyiyse kabul et.
- Daha kötüyse e−Δ/T olasılıkla yine kabul et: yerel minimumdan kaçış.
- Sıcaklık T her adımda azalır (ör. T₀ = 100, soğuma oranı 0,003).
- Rastgele bir çözüm popülasyonu ile başla (ör. 100 birey).
- Uygunluğa göre seç, çaprazla (rastgele kesim noktası), küçük olasılıkla mutasyon uygula (0,05).
- Kuşaklar boyunca iyi çözümler çoğalır.
Monte Carlo Algoritmaları
Sözde Rastgele Sayılar
- Bilgisayar gerçek rastgelelik yerine sözde rastgele (pseudo-random) sayı üretir: deterministik ama rastgele görünen bir dizi.
- Doğrusal eşlik üreteci (LCG): Xk+1 = (a · Xk + c) mod m.
java.util.Random: a = 25214903917, c = 11, m = 248. - Aynı tohum (seed) aynı diziyi verir:
new Random(42)ile çalıştırmalar tekrarlanabilir (hata ayıklama, deney). - Kriptografi için
SecureRandom; çok iş parçacıklı koddaThreadLocalRandom.
zar.nextInt(n)→ 0 … n − 1alt + zar.nextInt(ust − alt + 1)→ alt … ustzar.nextDouble()→ [0, 1)zar.nextInt(6) + 1→ zar atışı: 1 … 6
Özet
Özet
| Konu | Hatırlanacaklar |
|---|---|
| Rastgele algoritma | girdi + rastgele bitler; süre/çıktı rastgele değişken; beklenti algoritmanın seçimleri üzerinden |
| Las Vegas | her zaman doğru, süre rastgele: QuickSort, QuickSelect, BogoSort |
| Monte Carlo | süre sınırlı, küçük hata olasılığı; tekrarla qk'ya iner |
| Fisher–Yates | j = nextInt(i + 1), Θ(n), n! sonuç eşit olasılıklı; saf karıştırma yanlı |
| BogoSort | p = 1/n!, beklenen Θ(n · n!), en kötü sınırsız |
| Rastgele QuickSort | beklenen ≈ 1,39 n log₂ n karşılaştırma, her girdi için O(n log n); en kötü O(n²) |
| Miller–Rabin | n − 1 = 2sd; hata ≤ 4−k; "bileşik" kesin |
| Karger | rastgele kenar büzme; başarı ≥ 2/(n(n−1)); çok kez tekrarla |
| π tahmini | 4 · iç / n; hata ∝ 1/√n |
Özet
Etkileşimli Simülatörler
Özet
Sık Yapılan Hatalar
nextInt(n) ile takas yanlıdır (nn yol, n! permütasyon). Doğrusu nextInt(i + 1).int ile x * x % n, n > 46 340 için taşar. long, Math.multiplyHigh ya da BigInteger.modPow kullanın.Random paylaşın; Karger'de kenarı düzgün seçin (önce düğüm, sonra komşu seçmek düzgün değildir).Özet
Örnek Problemler
- Fisher–Yates
[1, 2, 3, 4]dizisine uygulanıyor; i = 3, 2, 1 için çekilen j değerleri 1, 2, 0. Sonuç nedir? - 5 farklı elemanlı bir dizide BogoSort'un ilk karıştırmada bitme olasılığı ve beklenen karıştırma sayısı nedir?
- Rastgele QuickSort'ta en küçük ve en büyük eleman hangi olasılıkla karşılaştırılır? Sıralı hâlde komşu iki eleman?
- Miller–Rabin: n = 25 için a = 7 ve a = 2 tabanlarıyla testi uygulayın.
- Monte Carlo ile 1000 noktanın 787'si çeyrek dairenin içine düştü. π tahmini nedir?
Cevapları göster
- i = 3, j = 1 → [1, 4, 3, 2]; i = 2, j = 2 → değişmez; i = 1, j = 0 → [4, 1, 3, 2].
- P = 1/5! = 1/120; beklenen karıştırma sayısı 120 (geometrik dağılım).
- z1 ile zn: 2/n (ilk pivot bu ikisinden biri olmalı). Komşular zi, zi+1: 2/2 = 1, her zaman karşılaştırılır.
- 24 = 23 · 3. a = 7: 73 ≡ 18, 18² ≡ 24 = n − 1 → geçer (7, 25 için güçlü yalancı). a = 2: 8, 14, 21 → 24 hiç görünmez → bileşik.
- π ≈ 4 · 787/1000 = 3,148.
Özet
Alıştırmalar
[3, 8, 2, 5, 1, 4, 7, 6]dizisindebolçağrılıyor ver = 5(pivot 4) çekiliyor. Bölme sonrası dizi ve dönüş değeri nedir?- Sıralı 8 elemanlı bir dizide ilk elemanı pivot seçen QuickSort kaç karşılaştırma yapar?
- Miller–Rabin'de hata olasılığını 10−6'nın altına indirmek için en az kaç tur gerekir?
- Karger'i 6 düğümlü bir çizgede (başarı ≥ 1/15) kaç kez tekrarlarsanız başarısızlık olasılığı 1/6'nın altına iner?
- Başarı olasılığı 1/3 olan ve sonucu doğrulanabilen bir Monte Carlo algoritmasını Las Vegas'a çevirin. Beklenen tekrar sayısı nedir?
Cevapları göster
- Pivot sona: [3, 8, 2, 5, 1, 6, 7, 4]; ≤ 4 olanlar 3, 2, 1 sola alınır → [3, 2, 1, 4, 8, 6, 7, 5], dönüş 3.
- Her düzeyde parça bir küçülür: 7 + 6 + … + 1 = n(n − 1)/2 = 28.
- 4−k < 10−6 → k ≥ 10 (4−10 ≈ 9,5 · 10−7).
- (14/15)T ≤ e−T/15 ≤ 1/6 → T ≥ 15 ln 6 ≈ 26,9 → 27 tekrar yeterli.
- Doğrulama başarılı olana kadar tekrar et: hep doğru yanıt (Las Vegas); beklenen tekrar 1/(1/3) = 3.
Özet
Kaynaklar
- R. Motwani ve P. Raghavan, Randomized Algorithms, Cambridge University Press, 1995.
- M. Mitzenmacher ve E. Upfal, Probability and Computing, 2. baskı, Cambridge University Press, 2017.
- Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022 (Bölüm 5, 7, 9, 31).
- C. A. R. Hoare, "Quicksort", The Computer Journal 5(1), 1962.
- M. O. Rabin, "Probabilistic Algorithm for Testing Primality", Journal of Number Theory 12(1), 1980.
- D. R. Karger, "Global Min-cuts in RNC, and Other Ramifications of a Simple Min-Cut Algorithm", SODA, 1993.
- D. E. Knuth, The Art of Computer Programming, Cilt 2, 3. baskı, 1997 (Bölüm 3.4.2: karıştırma).