Bölüm 11: Öncelikli Kuyruk

Bölüm 11: Öncelikli Kuyruk · Çalışma Soruları
Öncelikli kuyruk ADTListe ile uygulamaİkili heap ve dizi gösterimiUp-heap ve down-heapUyarlanabilir öncelikli kuyrukHeap oluşturma ve heap sortJava PriorityQueue
Sercan KÜLCÜ

Ç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
İşlemDönerKuyruk
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
İşlemDizi (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 → CA:3, D:3, B:1
ekle(E,4)E:4, A:3, D:3, B:1
cikar → EA:3, D:3, B:1
cikar → AD: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?

2015189107
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?

503040102035
503040102035

n = 6 ≠ 8 → dizi dolu değil, buyut çağrılmaz.

50304010203545

45 ilk boş konuma, heap[6]'ya yazılır; n = 7. Ağaç tam kalır.

50304010203545

yuzdur(6): i = 6 > 0 → döngüye girilir.

50304010203545

ebeveyn = (6 − 1)/2 = 2. heap[2] = 40 < 45 → return yok.

50304510203540

Takas (6 ↔ 2): 45 bir seviye çıktı, i = 2.

50304510203540

ebeveyn = 0: heap[0] = 50 ≥ 45 → return.

50304510203540

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
ekleDiziTakaslar
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).

11984725

Ç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?

121084973
121084973

En büyük her zaman kökte: max = 12.

310849712

Kök ile son öğe takas (0 ↔ 6), n = 6: 12 heap dışında. Yeni kök 3 sırayı bozar.

310849712

batir(0): çocuklar 10 ve 8 → büyük olan 10, j = 1.

103849712

3 < 10 → takas (0 ↔ 1), i = 1.

103849712

Çocuklar 4 (indis 3) ve 9 (indis 4) → j = 4.

109843712

3 < 9 → takas (1 ↔ 4), i = 4.

109843712

2·4 + 1 = 9 ≥ n = 6 → yaprak, döngü biter.

109843712

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İşlemDizi
37 ≥ 3, takas yok[2, 9, 4, 7, 1, 8, 5, 3]
24 ↔ 8[2, 9, 8, 7, 1, 4, 5, 3]
19 ≥ 7, 1, takas yok[2, 9, 8, 7, 1, 4, 5, 3]
02 ↔ 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ımDizi (| 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].
  • PriorityQueue varsayı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
xoffer sonrasıpollpq
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).

Son

Bölüm 11: Öncelikli Kuyruk: Çalışma Soruları
Konu anlatımı: Öncelikli Kuyruk sunumu
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.