🔢 7.9: Radix Sort (Basamak Sıralaması)

Basamak Basamak Sıralayarak O(d·n) Zaman!

📌 Bu Bölümde Öğrenecekleriniz

🔢

Basamak Prensibi

LSD vs MSD

O(d·n)

d: basamak sayısı

Stable

Counting Sort ile

🎯

Büyük Sayılar

Counting Sort'tan iyi

🤔 Radix Sort Nedir?

Radix Sort, sayıları basamak basamak sıralayan bir algoritmadır. Her basamak için stable bir sıralama (genellikle Counting Sort) kullanır.

💡 Neden Basamak Basamak?

Düşün: [170, 45, 75, 90, 802, 24, 2, 66] dizisini sıralamak istiyorsun.

  • Counting Sort: k = 802 → O(802) alan gerekir 😕
  • Radix Sort: 3 basamak, her biri k = 10 → Sadece O(10) alan! 🎉

LSD Radix Sort

Least Significant Digit - En sağdaki (birler) basamaktan başla. En yaygın kullanılan.

MSD Radix Sort

Most Significant Digit - En soldaki basamaktan başla. String sıralamasında kullanılır.

🎬 LSD Radix Sort Adımları

Adım 1: Maksimum Basamak Sayısını Bul

En büyük sayının kaç basamaklı olduğunu bul. Bu kadar tur döneceğiz.

max_num = max(arr)
d = len(str(max_num)) # veya log10 ile

Adım 2: Her Basamak İçin Counting Sort

Birler basamağından başla, her basamak için stable sıralama yap.

for i in range(d):
  counting_sort_by_digit(arr, i)

⚠️ Neden Stable Olmalı?

Önceki basamaklardaki sırayı korumak için! Birler basamağında [45, 75] sıralıydı. Onlar basamağında ikisi de 4-7 ama stability sayesinde sıra bozulmaz.

👁️ Adım Adım Görsel Örnek

Diziyi sıralayalım: [170, 45, 75, 90, 802, 24, 2, 66]

🔵 Tur 1: Birler Basamağına Göre (i=0)

Her sayının birler basamağına bak:

170, 45, 75, 90, 802, 24, 2, 66
Bucket 0
170, 90
Bucket 2
802, 2
Bucket 4
24
Bucket 5
45, 75
Bucket 6
66
Sonuç: [170, 90, 802, 2, 24, 45, 75, 66]

🟢 Tur 2: Onlar Basamağına Göre (i=1)

Her sayının onlar basamağına bak (tek basamaklılar için 0):

170, 90, 802, 02, 24, 45, 75, 66
Bucket 0
802, 2
Bucket 2
24
Bucket 4
45
Bucket 6
66
Bucket 7
170, 75
Sonuç: [802, 2, 24, 45, 66, 170, 75, 90]

🔴 Tur 3: Yüzler Basamağına Göre (i=2)

Her sayının yüzler basamağına bak:

802, 002, 024, 045, 066, 170, 075, 090
Bucket 0
2, 24, 45, 66, 75, 90
Bucket 1
170
Bucket 8
802
✅ Sıralı: [2, 24, 45, 66, 75, 90, 170, 802]

📊 Karmaşıklık Analizi

⏱️ Zaman

O(d·n)

d: basamak, n: eleman

💾 Alan

O(n + k)

k: taban (genelde 10)

🔄 Stable?

✅ Evet

Counting Sort kullanılırsa

🧮 O(d·n) vs O(n log n)

d = basamak sayısı = log10(max_value)

  • 32-bit integer: d ≤ 10, yani O(10n) ≈ O(n)
  • 64-bit integer: d ≤ 20, yani O(20n) ≈ O(n)
  • Karşılaştırma: Quick Sort O(n log n), n=1M için log n ≈ 20
  • Pratikte constant factor'lar önemli, Radix Sort çoğunlukla kazanır!

💻 Python Implementasyonu

Radix Sort - Python
# ====================================
# RADIX SORT (LSD) ALGORİTMASI
# ====================================

def counting_sort_by_digit(arr, exp):
    """
    Belirli bir basamağa göre Counting Sort uygula.
    
    exp: 1 (birler), 10 (onlar), 100 (yüzler), ...
    """
    n = len(arr)
    output = [0] * n
    count = [0] * 10  # 0-9 arası basamaklar
    
    # Sayma: Her basamağın kaç kez göründüğünü say
    for num in arr:
        digit = (num // exp) % 10
        count[digit] += 1
    
    # Kümülatif toplam
    for i in range(1, 10):
        count[i] += count[i - 1]
    
    # Çıktı oluştur (sondan başa - stability için)
    for i in range(n - 1, -1, -1):
        digit = (arr[i] // exp) % 10
        output[count[digit] - 1] = arr[i]
        count[digit] -= 1
    
    # Orijinal diziye kopyala
    for i in range(n):
        arr[i] = output[i]

def radix_sort(arr):
    """
    Radix Sort (LSD - Least Significant Digit)
    
    Zaman: O(d * n) - d: basamak sayısı
    Alan: O(n + 10) = O(n)
    Stable: Evet
    """
    if len(arr) == 0:
        return arr
    
    # Maksimum değeri bul (basamak sayısı için)
    max_val = max(arr)
    
    print(f"📊 Orijinal: {arr}")
    print(f"   Max değer: {max_val}")
    print("=" * 50)
    
    # Her basamak için Counting Sort
    exp = 1  # Birler, onlar, yüzler...
    digit_pos = 1
    
    while max_val // exp > 0:
        print(f"\n🔵 Tur {digit_pos}: {'Birler' if exp == 1 else 'Onlar' if exp == 10 else 'Yüzler' if exp == 100 else f'{exp}ler'} basamağı (exp={exp})")
        counting_sort_by_digit(arr, exp)
        print(f"   Sonuç: {arr}")
        
        exp *= 10
        digit_pos += 1
    
    return arr

# ============ TEST ============
print("🔢 RADIX SORT (LSD)")
print("=" * 50)

dizi = [170, 45, 75, 90, 802, 24, 2, 66]
radix_sort(dizi)
print(f"\n✅ Sıralı dizi: {dizi}")

print("\n" + "=" * 50)
print("BÜYÜK SAYILARLA TEST")
print("=" * 50)

dizi2 = [329, 457, 657, 839, 436, 720, 355]
radix_sort(dizi2)
print(f"\n✅ Sıralı dizi: {dizi2}")
Çıktı bekleniyor...

⚖️ Counting Sort vs Radix Sort

Özellik Counting Sort Radix Sort
Zaman O(n + k) O(d·n)
Alan O(k) O(n + 10) ≈ O(n)
[0, 100] arası ✅ İdeal (k=101) Gereksiz
[0, 10⁹] arası ❌ k çok büyük! ✅ d=10 tur yeterli

🎯 Ne Zaman Radix Sort Kullanılır?

✅ İdeal Durumlar

  • Büyük integer'lar: 32/64-bit değerler
  • Sabit uzunluk string: Posta kodları, telefon numaraları
  • n >> k olduğunda: Çok fazla eleman, küçük taban
  • Stability gerektiğinde: Guaranteed stable

❌ Uygun Olmayan Durumlar

  • Float sayılar: Basamak mantığı çalışmaz
  • Değişken uzunluk string: Karmaşıklaşır
  • Küçük n: Overhead fazla
  • Negatif sayılar: Ekstra işlem gerekir

📋 Bölüm Özeti

🔢 Algoritma

Basamak basamak Counting Sort

⏱️ Zaman

O(d·n)

💾 Alan

O(n + k)

✨ Özellik

Stable, büyük int için ideal