Bölüm 11: Öncelikli Kuyruk
Çoktan Seçmeli · Öncelikli Kuyruk ADT
Soru 1: Eşit Öncelikler
Min-öncelikli kuyrukta Ece ve Naz aynı önceliğe (1) sahiptir ve Ece önce gelmiştir. Ece'nin Naz'dan önce çıkmasını garanti etmek için ne yapılmalıdır?
Doğru: B. Sıra numaraları hep farklı olduğundan eşitlik bozulur: öncelik aynıysa küçük sıra numaralı (önce gelen) önce çıkar. A en çekici yanlış: heap (ve Java PriorityQueue) eşit anahtarlar için FIFO garantisi vermez.
Klasik Soru · Öncelikli Kuyruk ADT
Soru 2: İşlem Dizisi
Boş bir min-öncelikli kuyrukta aşağıdaki işlemler sırayla yapılıyor. Değer döndüren her işlemin sonucunu ve o anda kuyruğun içeriğini yazınız.
insert(8, P) insert(3, Q) insert(6, R) min() removeMin() insert(2, S) removeMin() removeMin() size() removeMin() removeMin()
Cevabı göster
| İşlem | Döner | Kuyruk |
|---|---|---|
| min() | (3,Q) | {(3,Q), (6,R), (8,P)} |
| removeMin() | (3,Q) | {(6,R), (8,P)} |
| removeMin() | (2,S) | {(6,R), (8,P)} |
| removeMin() | (6,R) | {(8,P)} |
| size() | 1 | {(8,P)} |
| removeMin() | (8,P) | { } |
| removeMin() | null | { } (boş kuyruk) |
min() öğeyi döndürür ama çıkarmaz; removeMin() çıkarır. (2,S) sonradan eklense de en küçük anahtar olduğu için hemen öne geçer. Boş kuyrukta removeMin() null döndürür.
Adım Adım Çalıştırma · Liste ile Uygulama
Soru 3: Sırasız Dizide removeMin
Sırasız dizide removeMin() çağrılıyor. Hangi değer döner ve çağrıdan sonra dizi nasıl olur?
İlk aday: indis 0 (7). Sırasız dizide en küçüğün yeri bilinmez.
a[1] = 4 < a[0] = 7 → yeni en küçük, enk = 1.
a[2] = 9 ≥ 4 → enk değişmez.
a[3] = 2 < 4 → enk = 3.
a[4] = 6 ≥ 2 → enk değişmez.
k = 5 = n → tarama bitti: 4 karşılaştırma. Her removeMin tüm diziyi tarar → O(n).
min = a[3] = 2 saklanır.
Son öğe (6) boşluğa taşınır, n = 4. Sıra önemsiz olduğundan kaydırma yok: O(1).
return 2. Kalan dizi [7, 4, 9, 6] yine sırasız.
public int removeMin() { int enk = 0; for (int k = 1; k < n; k++) if (a[k] < a[enk]) enk = k; int min = a[enk]; a[enk] = a[n - 1]; n--; return min; } // a = [7, 4, 9, 2, 6], n = 5
Çoktan Seçmeli · Liste ile Uygulama
Soru 4: n Ekleme + n Çıkarma
Boş bir öncelikli kuyruğa n öğe eklenip ardından n kez removeMin() yapılıyor. Sırasız liste, sıralı liste ve ikili heap uygulamalarında toplam maliyet sırasıyla nedir?
Doğru: C. Sırasız: n·O(1) + n·O(n) = O(n²). Sıralı: n·O(n) + n·O(1) = O(n²). Heap: 2n·O(log n) = O(n log n). A çekici yanlış: sırasız listede ekleme ucuzdur ama her removeMin tüm listeyi tarar. n = 10⁶ için fark ≈ 50.000 kat.
Klasik Soru · Liste ile Uygulama
Soru 5: Öncelikli Kuyruk İzleme
Sıralı dizi ile gerçeklenen max-öncelikli kuyrukta (büyük sayı = yüksek öncelik, eşitlerde geliş sırası) sırasıyla ekle(A,3), ekle(B,1), ekle(C,4), ekle(D,3), cikar(), ekle(E,4), cikar(), cikar() yapılıyor. cikar() çağrıları ne döndürür ve sonunda dizi nedir?
Cevabı göster
| İşlem | Dizi (veri:öncelik) |
|---|---|
| ekle(A,3) | A:3 |
| ekle(B,1) | A:3, B:1 |
| ekle(C,4) | C:4, A:3, B:1 |
| ekle(D,3) | C:4, A:3, D:3, B:1 |
| cikar → C | A:3, D:3, B:1 |
| ekle(E,4) | E:4, A:3, D:3, B:1 |
| cikar → E | A:3, D:3, B:1 |
| cikar → A | D:3, B:1 |
Çıkanlar: C, E, A; son dizi [D:3, B:1]. D, eşit öncelikli A'nın arkasına girer (3 < 3 değil). E, A'dan sonra gelse de önce çıkar: sırayı geliş değil öncelik belirler.
Çoktan Seçmeli · Liste ile Uygulama
Soru 6: Eşit Öncelik
Öncelikli kuyruğun ekle() metodundaki koşul < yerine <= yapılıyor. Boş kuyrukta ekle(X,3), ekle(Y,3), ekle(Z,1) sonrası cikar() ne döndürür?
int i = boyut; while (i > 0 && dizi[i-1].oncelik <= p) { dizi[i] = dizi[i - 1]; // sağa kaydır i--; } dizi[i] = new Oge<>(veri, p); boyut++;
<= ile eşit öncelikli X de sağa kaydırılır: [Y:3, X:3, Z:1]. Dizi yine büyükten küçüğe sıralıdır (C yanlış), ama eşitlerde FIFO bozulur. Asıl koddaki < sayesinde X önde kalırdı; A, orijinal kodun davranışıdır.
Klasik Soru · İkili Heap
Soru 7: Heap mi, Değil mi?
Aşağıdaki ağaçta her ebeveyn çocuklarından büyüktür. Bu ağaç bir max-heap midir? Değilse hangi özellik bozuktur?
Cevabı göster
Max-heap değildir. Heap-sıra özelliği sağlanır (20 ≥ 15, 18; 15 ≥ 9; 18 ≥ 10, 7) ama tam ikili ağaç özelliği bozuktur: son seviye soldan sağa dolmamış; 15'in sağ çocuğu yokken 18'in çocukları var.
Dizi gösteriminde bu, indis 4'ün boş kalması demektir: [20, 15, 18, 9, _, 10, 7]. Heap'te dizi boşluksuz olmalıdır; yeni öğe hep ilk boş konuma (indis n) gelir.
Heap = tam ikili ağaç ve heap-sıra özelliği; ikisi birlikte gerekir.
Çoktan Seçmeli · İkili Heap
Soru 8: Geçerli Min-Heap Dizisi
Hangisi geçerli bir min-heap dizisidir (0 tabanlı)?
Doğru: C. Her i için a[(i−1)/2] ≤ a[i] olmalı: 1 ≤ 3, 2; 3 ≤ 6, 4; 2 ≤ 5. A'da indis 1'deki 4 > çocuğu 3 (indis 3): kök en küçük olsa da yeterli değildir. B'de kök 2 > 1, D'de indis 1'deki 2 > çocuğu 0 (indis 4).
Çoktan Seçmeli · İkili Heap
Soru 9: heapMi Sonucu
Aşağıdaki çağrı ne döndürür?
static boolean heapMi(int[] a) { for (int i = 1; i < a.length; i++) { int e = (i - 1) / 2; if (a[e] < a[i]) return false; } return true; } heapMi(new int[]{9, 6, 8, 3, 7, 8, 1});
Doğru: D. i = 1…3 geçerlidir (9 ≥ 6, 8; 6 ≥ 3). i = 4: e = 1, a[1] = 6 < a[4] = 7 → false. C yanlış: koşul katı (<) olduğundan eşitlik heap'i bozmaz; zaten oraya gelinmez. Kontrol en kötü n − 1 karşılaştırma: O(n).
Adım Adım Çalıştırma · Ekleme ve Silme
Soru 10: Max-Heap'e Ekleme
Kapasitesi 8 olan max-heap heap = [50, 30, 40, 10, 20, 35] (n = 6) üzerinde ekle(45) çağrılıyor. 45 kaç seviye yukarı çıkar ve son dizi nedir?
n = 6 ≠ 8 → dizi dolu değil, buyut çağrılmaz.
45 ilk boş konuma, heap[6]'ya yazılır; n = 7. Ağaç tam kalır.
yuzdur(6): i = 6 > 0 → döngüye girilir.
ebeveyn = (6 − 1)/2 = 2. heap[2] = 40 < 45 → return yok.
Takas (6 ↔ 2): 45 bir seviye çıktı, i = 2.
ebeveyn = 0: heap[0] = 50 ≥ 45 → return.
Bitti: 45 bir seviye çıktı. Son dizi [50, 30, 45, 10, 20, 35, 40]. En çok h takas → O(log n).
public void ekle(int x) { if (n == heap.length) buyut(2 * n); heap[n] = x; n++; yuzdur(n - 1); } private void yuzdur(int i) { while (i > 0) { int ebeveyn = (i - 1) / 2; if (heap[ebeveyn] >= heap[i]) return; yerDegistir(i, ebeveyn); i = ebeveyn; } }
Klasik Soru · Ekleme ve Silme
Soru 11: Art Arda Ekleme
Kapasitesi 4 olan boş bir max-heap'e sırasıyla 4, 9, 2, 7, 11, 5, 8 ekleniyor. Her eklemeden sonra dizi nedir ve kapasite ne zaman büyür?
Cevabı göster
| ekle | Dizi | Takaslar |
|---|---|---|
| 4 | [4] | - |
| 9 | [9, 4] | 9↔4 |
| 2 | [9, 4, 2] | - |
| 7 | [9, 7, 2, 4] | 7↔4 |
| 11 | [11, 9, 2, 4, 7] | 11↔7, 11↔9 |
| 5 | [11, 9, 5, 4, 7, 2] | 5↔2 |
| 8 | [11, 9, 8, 4, 7, 2, 5] | 8↔5 |
11 eklenirken n = 4 = kapasite olduğundan önce buyut(8) çalışır (4 öğe kopyalanır).
Çoktan Seçmeli · Ekleme ve Silme
Soru 12: Neden Büyük Çocuk?
Max-heap'te silMax sonrası köke taşınan 3'ün sol çocuğu 8, sağ çocuğu 9'dur. Down-heap 3'ü hangi çocukla yer değiştirmelidir?
Doğru: B. 9 çıkarsa yeni kök 9'un çocukları 8 ve 3 olur; sıra korunur. 8 çıksaydı (A, C) kök 8'in çocuğu 9 olurdu: 8 < 9, heap-sıra bozulur. Min-heap'te ise küçük çocuk seçilir.
Adım Adım Çalıştırma · Ekleme ve Silme
Soru 13: silMax ve Down-Heap
Max-heap heap = [12, 10, 8, 4, 9, 7, 3] (n = 7) üzerinde silMax() çağrılıyor. Ne döner ve son dizi nedir?
En büyük her zaman kökte: max = 12.
Kök ile son öğe takas (0 ↔ 6), n = 6: 12 heap dışında. Yeni kök 3 sırayı bozar.
batir(0): çocuklar 10 ve 8 → büyük olan 10, j = 1.
3 < 10 → takas (0 ↔ 1), i = 1.
Çocuklar 4 (indis 3) ve 9 (indis 4) → j = 4.
3 < 9 → takas (1 ↔ 4), i = 4.
2·4 + 1 = 9 ≥ n = 6 → yaprak, döngü biter.
return 12. Yeni heap [10, 9, 8, 4, 3, 7]; en çok ⌊log₂ n⌋ seviye → O(log n).
public int silMax() { int max = heap[0]; yerDegistir(0, n - 1); n--; batir(0); return max; } private void batir(int i) { while (2 * i + 1 < n) { int j = 2 * i + 1; if (j+1 < n && heap[j+1] > heap[j]) j++; if (heap[i] >= heap[j]) return; yerDegistir(i, j); i = j; } }
Klasik Soru · Ekleme ve Silme
Soru 14: Sağ Çocuk Sınırı Unutulursa
Bu batir'da j + 1 < n kontrolü unutulmuştur. Max-heap [9, 8, 3, 5, 4] (n = 5) üzerinde silMax() çağrılırsa heap'in ilk n öğesi ne olur?
private void batir(int i) { while (2 * i + 1 < n) { int j = 2 * i + 1; if (heap[j + 1] > heap[j]) j++; if (heap[i] >= heap[j]) return; yerDegistir(i, j); i = j; } }
Cevabı göster
- max = 9; 9 ↔ 4, n = 4:
[4, 8, 3, 5 | 9]. - i = 0: j = 1 (8 > 3); 4 < 8 → takas:
[8, 4, 3, 5 | 9]. - i = 1: j = 3; hatalı kod heap[4] = 9 > 5 diye j = 4 seçer (silinmiş öğe!); 4 < 9 → takas:
[8, 9, 3, 5 | 4].
Sonuç [8, 9, 3, 5]: silinen 9 geri gelmiş, 4 kaybolmuş, 9 > ebeveyni 8 → heap bozuk. Doğrusu [8, 5, 3, 4].
Düzeltme: if (j + 1 < n && heap[j + 1] > heap[j]) j++; (dizi tam doluysa hatalı kod ArrayIndexOutOfBoundsException da fırlatabilir).
Klasik Soru · Heap Oluşturma ve Heap Sort
Soru 15: Aşağıdan Yukarıya Heap Oluşturma
[2, 9, 4, 7, 1, 8, 5, 3] dizisini aşağıdan yukarıya yöntemle max-heap'e çeviriniz. Döngü hangi k'dan başlar ve her batir(k)'dan sonra dizi nedir?
Cevabı göster
n = 8 → ilk k = n/2 − 1 = 3 (son iç düğüm); indis 4–7 yapraktır, tek başına zaten heap.
| k | İşlem | Dizi |
|---|---|---|
| 3 | 7 ≥ 3, takas yok | [2, 9, 4, 7, 1, 8, 5, 3] |
| 2 | 4 ↔ 8 | [2, 9, 8, 7, 1, 4, 5, 3] |
| 1 | 9 ≥ 7, 1, takas yok | [2, 9, 8, 7, 1, 4, 5, 3] |
| 0 | 2 ↔ 9, 2 ↔ 7, 2 ↔ 3 | [9, 7, 8, 3, 1, 4, 5, 2] |
Sonuç: [9, 7, 8, 3, 1, 4, 5, 2]. Her batir(k) çağrısında k'nın alt ağaçları zaten heap'tir. Toplam O(n); n kez ekleme O(n log n) olurdu.
Çoktan Seçmeli · Heap Oluşturma ve Heap Sort
Soru 16: Neden O(n)?
15 düğümlü tam bir ikili ağaçta (h = 3) aşağıdan yukarıya heap oluşturma en kötü durumda toplam kaç takas yapar?
Doğru: D. Down-heap'te takas sayısı düğümün yüksekliği kadardır: 8 yaprak·0 + 4·1 + 2·2 + 1·3 = 11 ≤ n. A (34), aynı ağaca n kez eklemenin en kötü durumudur: up-heap maliyeti derinliğe bağlıdır ve düğümlerin çoğu derindedir: 2·1 + 4·2 + 8·3 = 34. Öğeler tek tek geliyorsa (çevrim içi) yine de ekleme tek seçenektir.
Klasik Soru · Heap Oluşturma ve Heap Sort
Soru 17: Heap Sort Elle
[3, 7, 2, 9, 5] dizisini heap sort ile artan sıraya diziniz: max-heap oluşturduktan sonra ve her “kökü sona al + batir” adımından sonra diziyi yazınız.
Cevabı göster
| Adım | Dizi (| sağı sıralı) |
|---|---|
| Oluştur (k = 1, 0) | [9, 7, 2, 3, 5] |
| son = 4: 9 sona | [7, 5, 2, 3 | 9] |
| son = 3: 7 sona | [5, 3, 2 | 7, 9] |
| son = 2: 5 sona | [3, 2 | 5, 7, 9] |
| son = 1: 3 sona | [2 | 3, 5, 7, 9] |
Sonuç: [2, 3, 5, 7, 9]. Oluşturma: k = 1'de 7 ↔ 9; k = 0'da 3 ↔ 9, 3 ↔ 7. Sonra n − 1 kez kök sona alınır ve heap boyutu bir küçülür. Oluşturma O(n) + n − 1 batir O(log n) = O(n log n); ek dizi yok.
Çoktan Seçmeli · Heap Oluşturma ve Heap Sort
Soru 18: Heap Sort Özellikleri
Heap sort için hangisi yanlıştır?
Doğru cevap C (yanlış ifade): kök ile sondaki öğenin uzak takasları eşit anahtarların sırasını değiştirebilir; heap sort kararlı değildir. D doğru: her adımda en büyük dizinin sonuna gider, bu yüzden max-heap artan sıra verir (min-heap azalan). A: hızlı sıralamanın O(n²) kötü durumu yoktur.
Klasik Soru · Heap Oluşturma ve Heap Sort
Soru 19: PriorityQueue Çıktısı
Aşağıdaki programın çıktısı nedir?
PriorityQueue<Integer> pq = new PriorityQueue<>(); for (int x : new int[]{7, 2, 9, 4, 1}) pq.offer(x); System.out.println(pq); System.out.print(pq.poll() + " "); System.out.println(pq.poll()); pq.offer(3); System.out.println(pq.peek() + " " + pq.size()); PriorityQueue<Integer> mx = new PriorityQueue<>(Comparator.reverseOrder()); mx.addAll(Arrays.asList(7, 2, 9)); System.out.println(mx.poll());
Cevabı göster
[1, 2, 9, 7, 4] 1 2 3 4 9
println(pq)iç diziyi (heap sırasını) yazar, sıralı değildir: 4 eklenince 7 ile, 1 eklenince 4 ve 2 ile takas edilir → [1, 2, 9, 7, 4].PriorityQueuevarsayılan olarak min-heap: poll → 1, poll → 2.- Kalan {4, 7, 9}; 3 eklenince peek → 3 (çıkarmaz), size → 4.
reverseOrder()ile max-heap: poll → 9.
Çoktan Seçmeli · Heap Oluşturma ve Heap Sort
Soru 20: PriorityQueue Sınıfı
Java'nın PriorityQueue sınıfı için hangisi doğrudur?
Doğru: A. Heap sıralı olmadığından belirli bir öğe dizide doğrusal aranır. B yanlış ve sık yapılan bir hatadır: varsayılan min-heap'tir; max için Comparator.reverseOrder(). Eşitlerde FIFO garantisi yoktur; thread-safe değildir (PriorityBlockingQueue kullanılır). offer/poll O(log n), peek O(1).
Klasik Soru · Heap Oluşturma ve Heap Sort
Soru 21: k'ıncı En Büyük
Yorumdaki a ve k ile çağrı ne döndürür ve döngü bittiğinde pq'da hangi öğeler kalır? Yöntemin maliyeti nedir?
static int kinciEnBuyuk(int[] a, int k) { PriorityQueue<Integer> pq = new PriorityQueue<>(); for (int x : a) { pq.offer(x); if (pq.size() > k) pq.poll(); } return pq.peek(); } // a = {4, 8, 1, 7, 3, 9, 2}, k = 3
Cevabı göster
| x | offer sonrası | poll | pq |
|---|---|---|---|
| 4, 8, 1 | {1, 4, 8} | - | {1, 4, 8} |
| 7 | {1, 4, 7, 8} | 1 | {4, 7, 8} |
| 3 | {3, 4, 7, 8} | 3 | {4, 7, 8} |
| 9 | {4, 7, 8, 9} | 4 | {7, 8, 9} |
| 2 | {2, 7, 8, 9} | 2 | {7, 8, 9} |
pq = {7, 8, 9} (en büyük üç öğe); peek() → 7 (3. en büyük).
Min-heap'in kökü, k büyüğün en küçüğüdür; küçük öğeler hemen atılır. Heap en çok k + 1 öğe tutar: zaman O(n log k), bellek O(k).