🐍 9.5: Python heapq Modülü

Python'un Yerleşik Heap Kütüphanesi

📚 heapq Modülü Nedir?

Daha önce heap veri yapısını sıfırdan nasıl yazacağımızı gördük. Ama iyi haber: Python bize hazır bir heap modülü sunuyor! heapq modülü sayesinde heap işlemlerini tek satırda yapabiliriz.

Python'un heapq modülünün özelliği şu: ayrı bir Heap sınıfı yok. Bunun yerine normal bir Python listesini heap olarak kullanır ve bize heappush, heappop gibi fonksiyonlar sağlar. Liste arka planda otomatik olarak heap özelliğini korur.

💡 Neden heapq Kullanmalıyız?

  • Hazır ve Optimize: Python ekibi tarafından yazılmış, C ile hızlandırılmış
  • Kolay Kullanım: Sadece import edip fonksiyonları çağırın
  • Hafıza Verimli: Ek veri yapısı oluşturmaz, listenizi yerinde düzenler
  • Güvenilir: Yıllardır test edilmiş, hatasız çalışıyor

⚠️ Kritik: Sadece Min Heap!

Python heapq modülü sadece Min Heap destekler. Yani en küçük eleman her zaman kökte (heap[0]'da) bulunur ve heappop() her zaman en küçük elemanı döndürür.

Peki Max Heap istiyorsam? Çözüm basit: Değerleri negatif yapın!

# Max Heap trick - negatif kullanımı
heap = []
heapq.heappush(heap, -10)  # 10'u eklemek için -10 kullan
heapq.heappush(heap, -30)  # 30'u eklemek için -30 kullan
heapq.heappush(heap, -20)  # 20'yi eklemek için -20 kullan

# En büyüğü çıkar: -(-30) = 30
biggest = -heapq.heappop(heap)  # 30 döner!

📋 heapq Fonksiyonları

heapq.heappush(heap, item)

Açıklama: Heap'e eleman ekler (O(log n))

Kullanım: heapq.heappush(my_heap, 5)

heapq.heappop(heap)

Açıklama: En küçük elemanı çıkarır ve döndürür (O(log n))

Kullanım: smallest = heapq.heappop(my_heap)

heapq.heapify(x)

Açıklama: Listeyi heap'e çevirir (O(n))

Kullanım: heapq.heapify(my_list)

heapq.heappushpop(heap, item)

Açıklama: Push + Pop tek işlemde (daha verimli)

Kullanım: result = heapq.heappushpop(heap, 10)

heapq.nlargest(n, iterable) / heapq.nsmallest(n, iterable)

Açıklama: En büyük/küçük n elemanı döndürür

Kullanım: top3 = heapq.nlargest(3, my_list)

🎮 İnteraktif heapq Demo

🔧 heapq İşlemleri

📊 Heap Durumu (min heap[0] = root)

Heap boş

📝 Python Kodu

import heapq
heap = []

📤 Çıktı

Heap hazır...

📝 Temel Kullanım

heapq Temelleri
import heapq

print("=== heapq Temel Kullanım ===\n")

# 1. Boş heap oluştur
heap = []
print(f"Boş heap: {heap}")

# 2. Eleman ekle (heappush)
heapq.heappush(heap, 5)
heapq.heappush(heap, 3)
heapq.heappush(heap, 7)
heapq.heappush(heap, 1)
print(f"Push sonrası: {heap}")
print(f"Min eleman (heap[0]): {heap[0]}")

# 3. En küçüğü çıkar (heappop)
smallest = heapq.heappop(heap)
print(f"\nPop: {smallest}")
print(f"Kalan heap: {heap}")

# 4. Listeyi heap'e çevir (heapify)
print("\n=== heapify ===")
data = [9, 4, 7, 1, 3, 8]
print(f"Önce: {data}")
heapq.heapify(data)
print(f"Sonra: {data}")

# 5. nlargest ve nsmallest
print("\n=== nlargest / nsmallest ===")
numbers = [15, 3, 8, 21, 7, 42, 1, 99]
print(f"Liste: {numbers}")
print(f"En büyük 3: {heapq.nlargest(3, numbers)}")
print(f"En küçük 3: {heapq.nsmallest(3, numbers)}")
Çıktı bekleniyor...

🔄 Max Heap (Negatif Trick)

Max Heap Oluşturma
import heapq

print("=== MAX HEAP (Negatif Trick) ===\n")

# Değerleri negatif yaparak max heap simüle et
max_heap = []

values = [10, 30, 20, 50, 40]
print(f"Eklenecek değerler: {values}")

# Negatif olarak ekle
for val in values:
    heapq.heappush(max_heap, -val)
    print(f"  Push {val} → heap: {[-x for x in max_heap]}")

print(f"\nMax heap (gerçek değerler): {[-x for x in max_heap]}")
print(f"Max eleman: {-max_heap[0]}")

# Pop ederken pozitife çevir
print("\nMax'tan küçüğe sırayla çıkar:")
while max_heap:
    value = -heapq.heappop(max_heap)
    print(f"  Pop: {value}")

# ===== Alternatif: nlargest =====
print("\n" + "=" * 40)
print("Alternatif: Sadece en büyük N lazımsa")
print("=" * 40)

data = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"Data: {data}")
print(f"En büyük 4: {heapq.nlargest(4, data)}")
print("(Heap kurmaya gerek yok!)")
Çıktı bekleniyor...

📦 Tuple ile Priority Queue

Tuple Kullanımı
import heapq

print("=== Tuple ile Priority Queue ===\n")

# (öncelik, veri) formatında
tasks = []

# Görevleri ekle
heapq.heappush(tasks, (2, "Rapor hazırla"))
heapq.heappush(tasks, (1, "ACİL: Sunuma hazırlan"))  # En öncelikli
heapq.heappush(tasks, (3, "Mail cevapla"))
heapq.heappush(tasks, (1, "ACİL: Toplantıya git"))

print("Görevler öncelik sırasında:")
while tasks:
    priority, task = heapq.heappop(tasks)
    print(f"  [{priority}] {task}")

# ===== Obje ile kullanım =====
print("\n" + "=" * 40)
print("Nesne ile kullanım (key fonksiyonu)")
print("=" * 40)

class Task:
    def __init__(self, name, priority):
        self.name = name
        self.priority = priority

    def __repr__(self):
        return f"Task({self.name}, p={self.priority})"

# Wrapper ile
task_list = [
    (3, Task("Email", 3)),
    (1, Task("Sunuş", 1)),
    (2, Task("Kod", 2)),
]
heapq.heapify(task_list)

print("Task objeler (öncelik sırasında):")
while task_list:
    priority, task = heapq.heappop(task_list)
    print(f"  {task}")
Çıktı bekleniyor...

📊 heapq vs Alternatifler

Özellik heapq Sıralı Liste queue.PriorityQueue
Push O(log n) ✅ O(n) O(log n)
Pop O(log n) ✅ O(1) O(log n)
Thread-safe ❌ Hayır ❌ Hayır ✅ Evet
Kullanım Tek thread, hız önemli Küçük veri, basit Multi-thread

📋 Özet

✅ Bu Bölümde Öğrendikleriniz

  • heapq: Python'un min heap modülü
  • heappush/heappop: O(log n) ekleme/çıkarma
  • heapify: O(n) listeyi heap'e çevir
  • Max Heap: Negatif değer kullan
  • nlargest/nsmallest: Top-K problemleri için
  • Tuple: (öncelik, veri) ile priority queue