Bölüm 8: Kuyruk ve Deque

Bölüm 8: Kuyruk ve Deque · Çalışma Soruları
Kuyruk ADT ve FIFODizi ile kuyrukDairesel kuyrukBağlı liste ile kuyrukDeque ve kayan pencereUygulamalar
Sercan KÜLCÜ

Çoktan Seçmeli · Kuyruk ADT

Soru 1: FIFO Sırası

Boş bir kuyruğa sırasıyla enqueue(4), enqueue(7), dequeue(), enqueue(1), enqueue(9), dequeue() uygulanıyor. Sonunda first() ne döndürür?

FIFO: ilk dequeue 4'ü, ikincisi 7'yi çıkarır; kuyruk (önden arkaya) 1, 9 → first() = 1. 9 diyen yığın (LIFO) gibi düşünmüştür: önde son eklenen değil, en eski öğe durur.

Çoktan Seçmeli · Kuyruk ADT

Soru 2: Hata Fırlatan Çağrı

Boş bir Queue<Integer> q = new LinkedList<>() üzerinde hangi çağrı NoSuchElementException fırlatır?

Hata fırlatan üçlü add/remove/element; offer/poll/peek özel değer döndürür: boşta poll ve peek null, offer başarıda true. peek'in de hata vereceğini sanmak yaygındır; istisna fırlatan karşılığı element()'tir.

Klasik Soru · Kuyruk ADT

Soru 3: Java Kuyruğu Çıktısı

Programın çıktısı nedir?

Queue<Integer> q = new ArrayDeque<>();
for (int i = 1; i <= 4; i++)
    q.offer(i * 3);
q.poll();
q.offer(q.poll() + q.peek());
System.out.println(q.peek() + " " + q.size()
                   + " " + q);
while (q.size() > 1)
    q.poll();
System.out.println(q.poll() + " " + q.poll());
Cevabı göster
  • Döngü: [3, 6, 9, 12]; poll() 3'ü çıkarır → [6, 9, 12].
  • Argüman soldan sağa: poll() → 6 (kuyruk [9, 12]), peek() → 9; 15 arkaya eklenir → [9, 12, 15].
  • Önde 9, boyut 3.
  • while 9 ve 12'yi atar; sonra poll() → 15, kuyruk boş olduğundan ikinci poll() → null (istisna yok).

Çıktı:

9 3 [9, 12, 15]
15 null

Klasik Soru · Dizi ile Kuyruk

Soru 4: Basit Dizi Kuyruğunun Sorunu

Kapasitesi N = 6 olan basit (dairesel olmayan) dizi kuyruğu on = 0, arka = −1 ile başlıyor. enqueue 10, 20, 30, 40; üç kez dequeue(); enqueue 50, 60 yapılıyor. Son durumda on ve arka nedir ve ardından gelen enqueue(70) neden yapılamaz?

Cevabı göster
  • Eklemede arka++, çıkarmada on++; öğeler kaydırılmaz.
  • Dört ekleme → arka = 3; üç çıkarma (10, 20, 30) → on = 3; 50 ve 60 → arka = 5.
  • Son durum: on = 3, arka = 5; kuyruk 40, 50, 60 (yalnızca 3 öğe).
  • arka = N − 1 olduğu için kuyruk “dolu” görünür; oysa indis 0–2 boştur ve basit dizi kuyruğu boşalan yuvaları yeniden kullanamaz.

Çözüm 1: her dequeue'da öğeleri sola kaydırmak → dequeue O(n). Çözüm 2: dairesel dizi, indis (i + 1) % N ile başa sarar → her işlem O(1).

Çoktan Seçmeli · Dizi ile Kuyruk

Soru 5: Ekleme İndisi

Dairesel kuyruk bas (ilk öğenin indisi), boyut (öğe sayısı) ve N = dizi.length ile tutuluyor. ekle() yeni öğeyi hangi indise yazar?

Son öğeden sonraki yuva bas + boyut'tur; % N dizinin sonundan başa sarmayı sağlar. (bas + boyut − 1) % N son öğenin kendisidir; mod'suz A ise dizinin dışına taşabilir (ArrayIndexOutOfBoundsException). D, dequeue sonrası yeni bas'tır.

Çoktan Seçmeli · Dizi ile Kuyruk

Soru 6: Bir Yuvayı Boş Bırakma

Dairesel kuyrukta sayaç tutulmuyor; “bir yuvayı boş bırakma” yöntemi kullanılıyor (bas: ilk öğe, arka: sonraki yazma yeri). N = 10 ise kuyruk en fazla kaç öğe saklar ve dolu koşulu nedir?

bas == arka boş koşuludur; dolu ile karışmaması için bir yuva hep boş bırakılır → N − 1 = 9 öğe. Yalnızca bas ve arka ile 10 öğe saklanırsa (A) boş ve dolu kuyrukta ikisi aynı yuvayı gösterir; durumlar ayırt edilemez. Diğer çözüm boyut sayacıdır (dolu: boyut == N).

Adım Adım Çalıştırma · Dizi ile Kuyruk

Soru 7: Dairesel Kuyrukta Başa Sarma

Kapasitesi 4 olan dairesel kuyrukta son satırdaki cikar() ne yazdırır ve sonunda bas ile boyut kaç olur?

00bas ekle→010203
00bas ekle→010203

Dizi 0'larla dolu ama mantıksal olarak boş.

100bas01ekle→0203

ekle(10): indis (0 + 0) % 4 = 0.

100bas20102ekle→03

ekle(20): indis (0 + 1) % 4 = 1.

100bas20130203ekle→

ekle(30): indis (0 + 2) % 4 = 2.

100201bas30203ekle→

cikar() → 10; bas 0 → 1. Değer dizide kalır ama artık kuyrukta değildir.

100201302bas03ekle→

cikar() → 20; bas 1 → 2. Değer dizide kalır ama artık kuyrukta değildir.

100ekle→201302bas403

ekle(40): indis (2 + 1) % 4 = 3.

500201ekle→302bas403

ekle(50): indis (2 + 2) % 4 = 0. Dizinin sonu geçildi, başa sarıldı.

500601302bas403

ekle(60): indis (2 + 3) % 4 = 1. Dizinin sonu geçildi, başa sarıldı. Kuyruk doldu.

500601302ekle→403bas

cikar() → 30 yazdırılır (en eski öğe). Son durum: bas = 3, boyut = 3; kuyruk 40, 50, 60.

int[] d = new int[4];
int bas = 0, boyut = 0;
void ekle(int x) {
    d[(bas + boyut) % d.length] = x;
    boyut++;
}
int cikar() {
    int x = d[bas];
    bas = (bas + 1) % d.length;
    boyut--;
    return x;
}
// ekle(10); ekle(20); ekle(30);
// cikar(); cikar();
// ekle(40); ekle(50); ekle(60);
// System.out.println(cikar());

Klasik Soru · Dizi ile Kuyruk

Soru 8: Dolu Kuyruğu Büyütme

Dolu dairesel kuyrukta dizi = [F, G, C, D, E], bas = 2, boyut = 5. ekle(H) çağrısından sonra dizi, bas ve boyut ne olur?

private void buyut(int yeniKap) {
  E[] yeni = (E[]) new Object[yeniKap];
  for (int k = 0; k < boyut; k++)
    yeni[k] = dizi[(bas + k) % dizi.length];
  dizi = yeni;
  bas = 0;
}
public void ekle(E oge) {
  if (boyut == dizi.length)
    buyut(2 * dizi.length);
  dizi[(bas + boyut) % dizi.length] = oge;
  boyut++;
}
Cevabı göster
  • boyut == 5 → buyut(10).
  • k = 0..4: dizi[2] = C, dizi[3] = D, dizi[4] = E, dizi[0] = F, dizi[1] = G → yeni[0..4] = C, D, E, F, G; bas = 0.
  • H: (0 + 5) % 10 = 5 → dizi[5] = H; boyut = 6.

Sonuç: [C, D, E, F, G, H, _, _, _, _], bas = 0, boyut = 6. Kopyalama mantıksal sırayla yapıldığı için sıra korunur. Büyütme O(n) sürer, ama kapasite iki katına çıktığından ekle amortize O(1)'dir.

Çoktan Seçmeli · Dizi ile Kuyruk

Soru 9: Büyütmede Arrays.copyOf

Dolu kuyrukta dizi = [C, D, A, B], bas = 2 (sıra A, B, C, D). Büyütme yandaki satırla yapılıyor ve bas değişmiyor. ekle(E)'den sonra beş kez cikar() sırasıyla ne döndürür?

// buyut() yerine yazılan satır
dizi = Arrays.copyOf(dizi, 2 * dizi.length);
// bas = 2 olarak kalır

copyOf öğeleri aynı indislere kopyalar: [C, D, A, B, _, _, _, _], bas = 2. E, (2 + 4) % 8 = 6'ya yazılır; cikar dizi[2..6]'yı okur: A, B, null, null, E. Başa sarmış C ve D kaybolur. A şıkkı, öğeleri (bas + k) % N sırasıyla kopyalayan doğru buyut'un sonucudur; D, E'nin 4. indise yazıldığını varsayar.

Klasik Soru · Bağlı Liste ile Kuyruk

Soru 10: enqueue Hatası

Bağlı liste kuyruğunun bu enqueue metodunda bir hata var. Boş kuyrukta enqueue(10), enqueue(15) çağrılınca ne olur ve metot nasıl düzeltilir?

public void enqueue(int veri) {
    Dugum gecici = new Dugum(veri);
    if (bosMu()) {
        on = gecici;
    } else {
        arka.sonraki = gecici;
    }
    uzunluk++;
}
Cevabı göster
  • enqueue(10): kuyruk boş → on = düğüm(10); arka hiç atanmadığı için null kalır.
  • enqueue(15): boş değil → arka.sonraki erişimi → NullPointerException.

Düzeltme: if/else'ten sonra yeni düğüm her iki durumda da arka olmalı:

    }
    arka = gecici;      // eklendi
    uzunluk++;

Liste gezinilmediği için her enqueue O(1).

Klasik Soru · Kuyruk Türleri

Soru 11: Deque Çıktısı

ArrayDeque çift uçlu kuyruktur; push/pop baş uçta çalışır. Programın çıktısı nedir?

Deque<String> d = new ArrayDeque<>();
d.offerFirst("A");
d.offerLast("B");
d.push("C");
d.addLast("D");
System.out.print(d.pollLast() + " ");
System.out.print(d.pop() + " ");
d.offerFirst("E");
System.out.print(d.peekLast() + " " + d);
Cevabı göster
  • offerFirst A → [A]; offerLast B → [A, B]
  • push = addFirst → [C, A, B]; addLast D → [C, A, B, D]
  • pollLast → D; pop = removeFirst → C; deque [A, B]
  • offerFirst E → [E, A, B]; peekLast → B (çıkarmaz)

Çıktı: D C B [E, A, B]

Deque FIFO'ya bağlı değildir: yalnızca bir uçtan kullanılırsa yığın, bir uçtan ekleyip diğerinden çıkarılırsa kuyruk olur.

Çoktan Seçmeli · Kuyruk Türleri

Soru 12: onceki Referansı

Çift yönlü bağlı liste ile gerçeklenen deque'de her düğümün onceki referansını da tutmasının asıl nedeni nedir?

Tek yönlü listede sondan çıkarmak için sondan bir önceki düğüm baştan gezilerek bulunur: O(n). basaEkle tek yönlü listede de O(1)'dir (B). onceki her düğüme ek bir referans ekler, yani belleği artırır (D).

Klasik Soru · Kuyruk Türleri

Soru 13: Kayan Pencere Maksimumu

a = {4, 2, 1, 3, 6, 2, 1} için pencereMax(a, 3) ne döndürür?

int[] pencereMax(int[] a, int k) {
  int[] enb = new int[a.length - k + 1];
  Deque<Integer> d = new ArrayDeque<>();
  for (int i = 0; i < a.length; i++) {
    if (!d.isEmpty()
        && d.peekFirst() <= i - k)
      d.pollFirst();   // pencere dışı
    while (!d.isEmpty()
           && a[d.peekLast()] <= a[i])
      d.pollLast();    // aday değil
    d.offerLast(i);
    if (i >= k - 1)
      enb[i - k + 1] = a[d.peekFirst()];
  }
  return enb;
}
Cevabı göster
ia[i]d (indis)enb
040
120, 1
210, 1, 24
333 (0 pencere dışı; 2, 1 atıldı)3
4646
524, 56
614, 5, 66

Sonuç: [4, 3, 6, 6, 6]. Deque'de değerler önden arkaya azalır, en büyük önde durur. Her indis bir kez girer, en çok bir kez çıkar → O(n) (kaba kuvvet O(n·k)).

Klasik Soru · Uygulamalar

Soru 14: Round Robin Çizelgeleyici

Hazır kuyruğunda sırayla P1 (4 birim), P2 (7 birim), P3 (2 birim) var; round robin zaman dilimi (quantum) q = 3. Önden alınan süreç en fazla q birim çalışır, bitmezse arkaya döner. Her süreç hangi anda tamamlanır?

Cevabı göster
ZamanÇalışanKalanKuyruk (sonra)
0–3P11P2, P3, P1
3–6P24P3, P1, P2
6–8P30 → biterP1, P2
8–9P10 → biterP2
9–12P21P2
12–13P20 → biterboş

Tamamlanma: P3 = 8, P1 = 9, P2 = 13. Kalan süre dilimden kısaysa dilimin tamamı kullanılmaz. Her tur bir poll ve en çok bir offer: O(1).

Adım Adım Çalıştırma · Uygulamalar

Soru 15: Josephus Problemi

Kuyrukta önden arkaya A, B, C, D, E, F varken josephus(q, 2) hangi sırayla eleme yapar ve kimi döndürür?

qABCDEFön
qBCDEFAön

size 6 > 1 → tur başlar. i = 1: A önden alınıp arkaya geçer.

qCDEFAön

Öndeki B çıkarılır ve elenir. Kalan: 5 kişi.

qDEFACön

size 5 > 1 → tur başlar. i = 1: C önden alınıp arkaya geçer.

qEFACön

Öndeki D çıkarılır ve elenir. Kalan: 4 kişi.

qFACEön

size 4 > 1 → tur başlar. i = 1: E önden alınıp arkaya geçer.

qACEön

Öndeki F çıkarılır ve elenir. Kalan: 3 kişi.

qCEAön

size 3 > 1 → tur başlar. i = 1: A önden alınıp arkaya geçer.

qEAön

Öndeki C çıkarılır ve elenir. Kalan: 2 kişi.

qAEön

size 2 > 1 → tur başlar. i = 1: E önden alınıp arkaya geçer.

qEön

Öndeki A çıkarılır ve elenir. Kalan: 1 kişi.

q(boş)

size 1 → döngü biter; return E. Eleme sırası B, D, F, C, A; kazanan E. n − 1 tur, her tur k kuyruk işlemi: O(n·k).

String josephus(Queue<String> q, int k) {
  while (q.size() > 1) {
    for (int i = 1; i < k; i++)
      q.offer(q.poll()); // arkaya
    String elenen = q.poll();
    System.out.println(elenen + " elendi");
  }
  return q.poll();
}

Adım Adım Çalıştırma · Uygulamalar

Soru 16: İki Yığınla Kuyruk

Yorumdaki işlemler sonunda ne yazdırılır ve toplam kaç öğe gelen'den giden'e aktarılır?

gelen(boş)giden(boş)
gelen1üstgiden(boş)

enqueue(1): gelen.push(1) → O(1).

gelen21üstgiden(boş)

enqueue(2): gelen.push(2); üst solda.

gelen(boş)giden12üst

dequeue: giden boş → gelen'deki 2 ve 1 aktarılır. Aktarım sırayı ters çevirir; en eski öğe (1) üste çıkar.

gelen(boş)giden2üst

giden.pop() → 1 yazdırılır (FIFO).

gelen3üstgiden2üst

enqueue(3): gelen.push(3). giden'deki 2'ye dokunulmaz.

gelen3üstgiden(boş)

dequeue: giden boş değil → aktarım yok; giden.pop() → 2.

gelen(boş)giden3üst

dequeue: giden boş → gelen'deki 3 aktarılır.

gelen(boş)giden(boş)

giden.pop() → 3. Çıktı 1 2 3 = giriş sırası; toplam 3 aktarım. Her öğe en çok bir kez aktarılır → dequeue amortize O(1) (tek çağrı en kötü O(n)).

Deque<Integer> gelen = new ArrayDeque<>();
Deque<Integer> giden = new ArrayDeque<>();
void enqueue(int x) {
  gelen.push(x);
}
int dequeue() {
  if (giden.isEmpty())
    while (!gelen.isEmpty())
      giden.push(gelen.pop());
  return giden.pop();
}
// enqueue(1); enqueue(2);
// yaz(dequeue()); enqueue(3);
// yaz(dequeue()); yaz(dequeue());

Çoktan Seçmeli · Özet

Soru 17: PriorityQueue ve FIFO

Programın çıktısı nedir?

Queue<Integer> q = new PriorityQueue<>();
q.offer(5);
q.offer(1);
q.offer(3);
System.out.println(q.poll() + " " + q.poll());

PriorityQueue, Queue arayüzünü uygulasa da FIFO değildir: poll en küçük öğeyi (doğal sıra, min-öncelik) verir → 1, sonra 3. “5 1” diyen, değişkenin türü Queue olduğu için geliş sırası beklemiştir.

Son

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