⭐ 9.4: Priority Queue

Heap'in En Önemli Kullanımı!

🎯 Priority Queue Nedir?

Priority Queue, her elemanın bir önceliği olan kuyruktur. En yüksek öncelikli eleman her zaman ilk çıkar.

🆚 Normal Queue vs Priority Queue

Normal Queue (FIFO)

İlk giren ilk çıkar

[5, 2, 9, 1] → 5 çıkar
Priority Queue

En yüksek öncelikli çıkar

[5, 2, 9, 1] → 9 çıkar ⭐

🌍 Gerçek Hayattan Örnekler

  • Hastane Acil: Ağır hastalar önce (öncelik: hastalık ciddiyeti)
  • İşletim Sistemi: Kritik işler önce çalışır (öncelik: CPU priority)
  • Dijkstra Algoritması: En kısa yol bulma
  • Huffman Encoding: Veri sıkıştırma

🏥 İnteraktif Simülasyon: Hastane Acil Servisi

Gerçek bir hastane acil servisini simüle edelim! Hastalar önceliklerine göre sıralanır.

🧪 Acil Servis Priority Queue

Yeni Hasta Ekle

Durum: Kuyrukta 0 hasta var

💻 Priority Queue İmplementasyonu

Priority Queue with Heap
class PriorityQueue:
    """Min Heap ile Priority Queue (en küçük öncelikli önce çıkar)"""

    def __init__(self):
        self.heap = []

    def parent(self, i):
        return (i - 1) // 2

    def left(self, i):
        return 2 * i + 1

    def right(self, i):
        return 2 * i + 2

    def swap(self, i, j):
        self.heap[i], self.heap[j] = self.heap[j], self.heap[i]

    def push(self, priority, data):
        """Eleman ekle - O(log n)"""
        item = (priority, data)
        self.heap.append(item)
        self._bubble_up(len(self.heap) - 1)
        print(f"➕ Push: Priority={priority}, Data={data}")

    def _bubble_up(self, i):
        """Yukarı yüzdür"""
        while i > 0:
            parent_idx = self.parent(i)
            if self.heap[i][0] < self.heap[parent_idx][0]:
                self.swap(i, parent_idx)
                i = parent_idx
            else:
                break

    def pop(self):
        """En yüksek öncelikli elemanı çıkar - O(log n)"""
        if not self.heap:
            return None

        if len(self.heap) == 1:
            item = self.heap.pop()
            print(f"➖ Pop: Priority={item[0]}, Data={item[1]}")
            return item[1]

        # Root'u kaydet
        min_item = self.heap[0]

        # Son elemanı root'a taşı
        self.heap[0] = self.heap.pop()
        self._bubble_down(0)

        print(f"➖ Pop: Priority={min_item[0]}, Data={min_item[1]}")
        return min_item[1]

    def _bubble_down(self, i):
        """Aşağı batır"""
        while True:
            left = self.left(i)
            right = self.right(i)
            smallest = i

            if left < len(self.heap) and self.heap[left][0] < self.heap[smallest][0]:
                smallest = left

            if right < len(self.heap) and self.heap[right][0] < self.heap[smallest][0]:
                smallest = right

            if smallest != i:
                self.swap(i, smallest)
                i = smallest
            else:
                break

    def peek(self):
        """En yüksek öncelikli elemana bak - O(1)"""
        if self.heap:
            return self.heap[0][1]
        return None

    def is_empty(self):
        return len(self.heap) == 0

    def size(self):
        return len(self.heap)

# Test: Hastane Acil Servisi
print("=== 🏥 Hastane Acil Servisi Simülasyonu ===\n")

pq = PriorityQueue()

# Hastalar geldi (öncelik: 1=kritik, 5=hafif)
print("Hastalar acile geldi:")
pq.push(3, "Ali (kırık kol)")
pq.push(1, "Ayşe (kalp krizi)") # En kritik!
pq.push(5, "Mehmet (nezle)")
pq.push(2, "Fatma (yanık)")
pq.push(4, "Can (baş ağrısı)")

print(f"\nKuyrukta {pq.size()} hasta var")
print(f"Sıradaki: {pq.peek()}")

# Hastaları sırayla muayene et
print("\n=== Muayene Sırası ===")
while not pq.is_empty():
    hasta = pq.pop()
    print(f"  → {hasta} muayene ediliyor")

print("\n✅ Tüm hastalar muayene edildi!")
Çıktı bekleniyor...

🐍 Python'da Priority Queue

Python heapq Modülü
import heapq

# Python heapq kullanımı
print("=== Python heapq (Min Heap) ===\n")

# Priority Queue oluştur
pq = []

# Eleman ekle: (öncelik, veri)
heapq.heappush(pq, (3, "Görev C"))
heapq.heappush(pq, (1, "Görev A - ÖNEMLİ!"))
heapq.heappush(pq, (2, "Görev B"))
heapq.heappush(pq, (1, "Görev A2 - ÖNEMLİ!"))

print(f"Priority Queue: {pq}")

# Elemanları çıkar (öncelik sırasında)
print("\n=== Görevler Sırayla ===")
while pq:
    priority, task = heapq.heappop(pq)
    print(f"Öncelik {priority}: {task}")

# Max Heap için trick: Negatif kullan!
print("\n=== Max Heap (Negatif Trick) ===")
max_heap = []

# Negatif öncelik ekle
heapq.heappush(max_heap, (-10, "A"))
heapq.heappush(max_heap, (-30, "C"))
heapq.heappush(max_heap, (-20, "B"))

print("Max Heap (negatif):", max_heap)

while max_heap:
    neg_priority, data = heapq.heappop(max_heap)
    priority = -neg_priority  # Geri çevir
    print(f"Öncelik {priority}: {data}")

# Önemli: heapq SADECE min heap!
# Max heap için negatif kullan veya kendi sınıf yaz
Çıktı bekleniyor...

📊 Priority Queue Karmaşıklık

İşlem Heap Sıralı Dizi Sırasız Dizi
Push O(log n) ✅ O(n) O(1)
Pop (min/max) O(log n) ✅ O(1) O(n)
Peek O(1) ✅ O(1) O(n)

Heap her iki işlemde de dengeli performans → En iyi seçim!

📋 Özet

✅ Bu Bölümde Öğrendikleriniz

  • Priority Queue: En yüksek/düşük öncelikli eleman önce çıkar
  • Heap ideal: Push O(log n), Pop O(log n), Peek O(1)
  • Python heapq: Min heap (max için negatif kullan)
  • Kullanım: Task scheduling, Dijkstra, Huffman, OS...
  • İnteraktif simülasyon: Hastane acil servisi örneği ile priority queue mantığını gördünüz