Bölüm 8: Kuyruklar ve Deque
Ç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.
while9 ve 12'yi atar; sonrapoll()→ 15, kuyruk boş olduğundan ikincipoll()→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++, çıkarmadaon++; öğ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 − 1olduğ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?
Dizi 0'larla dolu ama mantıksal olarak boş.
ekle(10): indis (0 + 0) % 4 = 0.
ekle(20): indis (0 + 1) % 4 = 1.
ekle(30): indis (0 + 2) % 4 = 2.
cikar() → 10; bas 0 → 1. Değer dizide kalır ama artık kuyrukta değildir.
cikar() → 20; bas 1 → 2. Değer dizide kalır ama artık kuyrukta değildir.
ekle(40): indis (2 + 1) % 4 = 3.
ekle(50): indis (2 + 2) % 4 = 0. Dizinin sonu geçildi, başa sarıldı.
ekle(60): indis (2 + 3) % 4 = 1. Dizinin sonu geçildi, başa sarıldı. Kuyruk doldu.
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);arkahiç atanmadığı içinnullkalır.enqueue(15): boş değil →arka.sonrakieriş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
offerFirstA → [A];offerLastB → [A, B]push=addFirst→ [C, A, B];addLastD → [C, A, B, D]pollLast→ D;pop=removeFirst→ C; deque [A, B]offerFirstE → [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.
Klasik Soru · Kuyruk Türleri
Soru 12: Deque ile Yığın ve Kuyruk
Deque (çift uçlu kuyruk) nedir? Bir deque yalnızca hangi işlemlerle yığın gibi, hangi işlemlerle kuyruk gibi kullanılır? Aşağıdaki kodun çıktısı nedir?
Deque<Integer> d = new ArrayDeque<>();
d.addFirst(1);
d.addLast(2);
d.addFirst(3);
d.pollLast();
d.addLast(4);
System.out.println(d);
Cevabı göster
- Deque, hem ön hem arka uçtan ekleme ve çıkarma yapılabilen kuyruktur.
- Ekleme ve çıkarma aynı uçtan yapılırsa (ör.
addFirst+pollFirst, ya dapush/pop) yığın olur. - Bir uçtan ekleyip öbür uçtan çıkarılırsa (ör.
addLast+pollFirst) kuyruk olur. - [1] → [1, 2] → [3, 1, 2] →
pollLast2'yi çıkarır → [3, 1] → [3, 1, 4]
Çıktı: [3, 1, 4]
Çoktan Seçmeli · Kuyruk Türleri
Soru 13: 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 14: 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
| i | a[i] | d (indis) | enb |
|---|---|---|---|
| 0 | 4 | 0 | |
| 1 | 2 | 0, 1 | |
| 2 | 1 | 0, 1, 2 | 4 |
| 3 | 3 | 3 (0 pencere dışı; 2, 1 atıldı) | 3 |
| 4 | 6 | 4 | 6 |
| 5 | 2 | 4, 5 | 6 |
| 6 | 1 | 4, 5, 6 | 6 |
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 15: 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ışan | Kalan | Kuyruk (sonra) |
|---|---|---|---|
| 0–3 | P1 | 1 | P2, P3, P1 |
| 3–6 | P2 | 4 | P3, P1, P2 |
| 6–8 | P3 | 0 → biter | P1, P2 |
| 8–9 | P1 | 0 → biter | P2 |
| 9–12 | P2 | 1 | P2 |
| 12–13 | P2 | 0 → biter | boş |
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 16: 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?
size 6 > 1 → tur başlar. i = 1: A önden alınıp arkaya geçer.
Öndeki B çıkarılır ve elenir. Kalan: 5 kişi.
size 5 > 1 → tur başlar. i = 1: C önden alınıp arkaya geçer.
Öndeki D çıkarılır ve elenir. Kalan: 4 kişi.
size 4 > 1 → tur başlar. i = 1: E önden alınıp arkaya geçer.
Öndeki F çıkarılır ve elenir. Kalan: 3 kişi.
size 3 > 1 → tur başlar. i = 1: A önden alınıp arkaya geçer.
Öndeki C çıkarılır ve elenir. Kalan: 2 kişi.
size 2 > 1 → tur başlar. i = 1: E önden alınıp arkaya geçer.
Öndeki A çıkarılır ve elenir. Kalan: 1 kişi.
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 17: İki Yığınla Kuyruk
Yorumdaki işlemler sonunda ne yazdırılır ve toplam kaç öğe gelen'den giden'e aktarılır?
enqueue(1): gelen.push(1) → O(1).
enqueue(2): gelen.push(2); üst solda.
dequeue: giden boş → gelen'deki 2 ve 1 aktarılır. Aktarım sırayı ters çevirir; en eski öğe (1) üste çıkar.
giden.pop() → 1 yazdırılır (FIFO).
enqueue(3): gelen.push(3). giden'deki 2'ye dokunulmaz.
dequeue: giden boş değil → aktarım yok; giden.pop() → 2.
dequeue: giden boş → gelen'deki 3 aktarılır.
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 18: 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.
Klasik Soru · Uygulamalar
Soru 19: İkilik Sayı Üretimi
ikilikSayiUret(7) hangi diziyi döndürür? Döngü bittiğinde q kuyruğunda neler kalır; genel n için kuyrukta kaç öğe kalır?
String[] ikilikSayiUret(int n) { String[] sonuc = new String[n]; Queue<String> q = new LinkedList<>(); q.offer("1"); for (int i = 0; i < n; i++) { sonuc[i] = q.poll(); q.offer(sonuc[i] + "0"); q.offer(sonuc[i] + "1"); } return sonuc; }
Cevabı göster
| i | poll → sonuc[i] | arkaya eklenen |
|---|---|---|
| 0 | 1 | 10, 11 |
| 1 | 10 | 100, 101 |
| 2 | 11 | 110, 111 |
| 3 | 100 | 1000, 1001 |
| 4 | 101 | 1010, 1011 |
| 5 | 110 | 1100, 1101 |
| 6 | 111 | 1110, 1111 |
Dönen dizi: {"1", "10", "11", "100", "101", "110", "111"}.
Kuyrukta 1000'den 1111'e (8–15) 8 öğe kalır. Her tur 1 öğe çıkarıp 2 ekler (net +1) ve kuyruk 1 öğeyle başlar → n + 1 öğe. FIFO sayesinde sayılar düzey düzey, artan sırada çıkar.
Çoktan Seçmeli · Kuyruk Türleri
Soru 20: Giriş Sınırlı Deque
Giriş sınırlı bir deque'e 1, 2, 3, 4 bu sırayla yalnızca arkadan ekleniyor; aralarda istenen anda önden ya da arkadan çıkarma yapılabiliyor. Çıkarılan değerlerin sırası hangisi olamaz?
D: 4 ilk çıkıyorsa dördü de eklenmiştir ve deque önden arkaya 1 2 3 4'tür; 4 arkadan alınınca uçlarda 1 ve 3 kalır, ortadaki 2 sıradaki çıkış olamaz. A: 1, 2, 3 ekle → arkadan 3, önden 1 → 4 ekle, arkadan 4 → 2. B: hepsini ekle → arka 4, ön 1, arka 3, 2. C: 1, 2 ekle → arka 2 → 3, 4 ekle → arka 4, ön 1, 3.
Çoktan Seçmeli · Kuyruk Türleri
Soru 21: Çıkış Sınırlı Deque
Çıkış sınırlı bir deque'e 1, 2, 3, 4 bu sırayla önden ya da arkadan ekleniyor; çıkarma yalnızca önden yapılıyor (aralarda istenen anda). Hangi çıkış sırası elde edilemez?
C: 4 ilk çıkıyorsa dördü de deque'tedir ve çıkış sırası deque'in önden arkaya okunuşudur. Her yeni sayı bir uca eklendiğinden 1, 2, 3 arasında en büyüğü (3) bir uçta olmalıdır; 1 3 2'de ortadadır. A: 1; 2 öne; 3 arkaya; 4 öne. B: 1; 2 arkaya; 3 öne; 4 öne. D: 1; 2 arkaya; 3 öne → 3, 1 çıkar → 4 öne → 4, 2 çıkar.
Çoktan Seçmeli · Dizi ile Kuyruk
Soru 22: Boş Yuvayla Öğe Sayısı
Sayaç tutulmayan dairesel kuyrukta “bir yuvayı boş bırakma” yöntemi kullanılıyor (bas: ilk öğe, arka: sonraki yazma yeri). N = 6, bas = 4, arka = 1 ise kuyrukta kaç öğe vardır ve kuyruk dolmadan en çok kaç ekleme daha yapılabilir?
C: Öğeler 4, 5, 0 indislerindedir: (arka − bas + N) % N = (1 − 4 + 6) % 6 = 3. En çok N − 1 = 5 öğe saklandığından 2 ekleme daha yapılabilir; sonra (arka + 1) % 6 == bas olur. B, boş bırakılması gereken yuvayı da doldurur. A, arka'yı son öğe sanıp indis 1'i de sayar. D, bas > arka olmasını dolu sanır; başa sarma olağandır.
Çoktan Seçmeli · Dizi ile Kuyruk
Soru 23: Dolu mu, Boş mu?
Sayaç tutulmuyor ve N = 5 yuvanın hepsi kullanılıyor; bas (ilk öğe) ve arka (sonraki yazma yeri) % 5 ile ilerliyor. Boş kuyrukta bas = arka = 0. Sırayla 3 ekleme, 1 çıkarma ve 3 ekleme yapılıyor. Son durum hangisidir?
D: Üç ekleme arka'yı 3'e, çıkarma bas'ı 1'e getirir; üç ekleme daha arka = (3 + 3) % 5 = 1 yapar. Kuyruk doludur ama boş kuyrukta da bas == arka'dır; A bu yüzden onu boş sanır. C mod almayı unutur (indis 6 dizinin dışındadır); B bas'ın çıkarmayla ilerlediğini unutur. Çözüm: boyut sayacı (dolu: boyut == N) ya da bir yuvayı boş bırakmak.