Bölüm 7: Yığın
Klasik Soru · Yığın ADT
Soru 1: push/pop Çıktısı
Aşağıdaki kod parçasının çıktısı nedir?
Deque<Integer> y = new ArrayDeque<>();
y.push(4); y.push(9); y.push(2);
System.out.print(y.pop() + " ");
y.push(7);
System.out.print(y.peek() + " ");
System.out.print(y.pop() + y.pop() + " ");
y.push(5);
System.out.print(y.size() + " " + y.peek());Cevabı göster
Çıktı: 2 7 16 2 5
- 4, 9, 2 eklenir; üstte 2 →
pop()2 döndürür (LIFO). Yığın (alt→üst): 4 9. - 7 eklenir;
peek()7'yi çıkarmadan döndürür. y.pop() + y.pop()önce tam sayı toplamıdır: 7 + 9 = 16. Yığın: 4.- 5 eklenir: yığın 4 5 →
size()2,peek()5.
Çoktan Seçmeli · Yığın ADT
Soru 2: Olası Çıkış Sıraları
1, 2, 3, 4 sayıları bu sırayla yığına push ediliyor; aralara istenen anda pop() serpiştirilebiliyor. Pop edilen değerlerin sırası aşağıdakilerden hangisi olamaz?
C: 4 ilk çıkıyorsa 1, 2, 3 hâlâ yığındadır ve üstte 3 vardır; sıradaki pop 3 olmak zorundadır, 2 olamaz. A ise mümkündür: push 1, 2, 3 → pop 3, pop 2 → push 4, pop 4 → pop 1.
Çoktan Seçmeli · Yığın ADT
Soru 3: Dizi Yığında top ve size
Kapasitesi kap olan dizi tabanlı yığında top üstteki öğenin indisidir ve boş yığında top = −1'dir. "Dolu" koşulu ve size() hangisidir?
B: Son geçerli indis kap − 1'dir; indisler 0'dan başladığı için öğe sayısı top + 1'dir. A en sık yapılan top/size karışıklığıdır: top == kap olduğunda veri[top] zaten dizinin dışındadır.
Klasik Soru · Gerçekleme
Soru 4: Çıkarılan Hücre
Nesne tutan dizi tabanlı yığının bu pop() metodu doğru değeri döndürür ama bir kusuru vardır. Kusur nedir ve nasıl düzeltilir?
public E pop() { if (isEmpty()) throw new RuntimeException("boş"); return veri[top--]; }
Cevabı göster
Çıkarılan öğenin referansı veri[top+1] hücresinde kalır. Yığın o nesneyi artık kullanmasa da dizi onu gösterdiği için çöp toplayıcı nesneyi temizleyemez (bellek sızıntısı, loitering).
public E pop() { if (isEmpty()) throw new RuntimeException("boş"); E x = veri[top]; veri[top--] = null; // bırak return x; }
İşlem yine O(1)'dir. İlkel tür (int[]) tutan yığında bu sorun yoktur.
Adım Adım Çalıştırma · Gerçekleme
Soru 5: Sınırlı Dizi Yığını İzleme
Derste yazılan DiziYigin sınıfıyla bu kod çalıştırılıyor. Her satırdan sonra veri dizisi ve top ne olur, program ne yazdırır?
3 hücrelik dizi, hepsi null; boş yığında top = −1.
top (−1) ≠ 2 → yer var. veri[++top] = 10: önce top 0 olur, sonra yazılır.
top 1 olur, veri[1] = 20.
x = veri[1] = 20 saklanır, hücre null yapılır, top 0'a iner; 20 yazdırılır (LIFO).
Boşalan 1. hücre yeniden kullanılır: veri[1] = 30.
top 2 olur, veri[2] = 40. Dizi artık dolu.
top() 40'ı çıkarmadan döndürür; size() = top + 1 = 3.
top == veri.length − 1 (2 == 2) → taşma istisnası. Dinamik dizi burada büyürdü.
DiziYigin<Integer> y = new DiziYigin<>(3);
y.push(10);
y.push(20);
System.out.println(y.pop());
y.push(30);
y.push(40);
System.out.println(y.top() + " " + y.size());
y.push(50);Klasik Soru · Gerçekleme
Soru 6: İki Katına Büyütme Maliyeti
Kapasitesi 1 olan ve dolunca kapasitesini iki katına çıkaran (eski öğeleri yeni diziye kopyalayan) boş bir yığına 9 kez push yapılıyor. Toplam kaç kopyalama ve kaç yazma yapılır, son kapasite kaçtır ve bu sonuç push'un amortize maliyeti hakkında ne söyler?
Cevabı göster
| push no. | 1 | 2 | 3 | 4 | 5 | 6–8 | 9 |
|---|---|---|---|---|---|---|---|
| büyütme | — | 1→2 | 2→4 | — | 4→8 | — | 8→16 |
| kopya | 0 | 1 | 2 | 0 | 4 | 0 | 8 |
Kopya: 1 + 2 + 4 + 8 = 15, yazma: 9, toplam 24; son kapasite 16.
24 < 3n = 27: n push'ta kopyalar 2 + 4 + 8 + … < 2n olduğundan toplam < 3n'dir; push başına ortalama < 3 → amortize O(1). Yine de büyütme yapan tek bir push (9. push) O(n) sürer; amortize sınır uzun bir işlem dizisinin ortalamasıdır.
Çoktan Seçmeli · Gerçekleme
Soru 7: Sabit Miktarda Büyütme
Dinamik dizi yığını, dolduğunda kapasitesini iki katına çıkarmak yerine 10 hücre artırıyor (10 → 20 → 30 → …). Boş yığına n push yapıldığında toplam maliyet ve push başına ortalama maliyet nedir?
C: Kopyalar 10 + 20 + 30 + … + n ≈ n²/20 → O(n²); n push'a bölünce push başına O(n). A yalnızca kapasite oranla (ör. ×2) büyütülünce doğrudur: o zaman kopyalar geometrik dizi oluşturur ve toplam < 3n kalır.
Çoktan Seçmeli · Gerçekleme
Soru 8: Dizi mi, Bağlı Liste mi?
Yığın gerçeklemeleri hakkındaki ifadelerden hangisi yanlıştır?
A yanlıştır: büyütme yapan push tüm öğeleri kopyalar, O(n) sürer; O(1) olan amortize maliyettir. D doğrudur: Stack Vector tabanlıdır ve senkronize olduğu için daha yavaştır. Bağlı listede öğe başına sonraki referansı ek bellek tutar.
Klasik Soru · Yığın Uygulamaları
Soru 9: Parantez Kontrolü İzleme
Dersteki gecerliMi metodu "[{()()}]{" girdisi için hangi değeri döndürür? Her karakterden sonra yığının durumunu yazarak gösterin.
Cevabı göster
| Karakter | İşlem | Yığın (alt→üst) |
|---|---|---|
| [ { ( | 3 × push | [ { ( |
| ) | pop ( ✓ | [ { |
| ( | push | [ { ( |
| ) | pop ( ✓ | [ { |
| } | pop { ✓ | [ |
| ] | pop [ ✓ | boş |
| { | push | { |
| (son) | yığın boş mu? | { kaldı |
Sonuç: false. Tüm kapanışlar doğru eşleşti ama sonda yığında kapanmamış { kaldı; return yigin.isEmpty() false verir. Zaman O(n), yığın en çok O(n).
Çoktan Seçmeli · Yığın Uygulamaları
Soru 10: Boş Yığın Kontrolü
gecerliMi metodundan işaretli satır silinirse aşağıdaki girdilerden hangisi istisna fırlatır?
for (char c : s.toCharArray()) { if (c == '(' || c == '[' || c == '{') { yigin.push(c); } else { if (yigin.isEmpty()) return false; // silindi char acik = yigin.pop(); if (!eslesir(acik, c)) return false; } } return yigin.isEmpty();
D: "()" eşleşip yığın boşaldıktan sonra gelen ikinci ) boş ArrayDeque'ten pop yapar → NoSuchElementException. A istisna vermez: sonda yığında ( kalır ve false döner. B'de ) gelince üstte [ vardır, eşleşmez → false; C geçerlidir → true.
Klasik Soru · Yığın Uygulamaları
Soru 11: Sonraki Büyük Öğe
sonrakiBuyuk(new int[]{6, 2, 9, 5, 5, 7, 1}) ne döndürür? Dizi sağdan sola gezilirken yığının değişimini gösterin.
for (int i = dizi.length-1; i >= 0; i--) { while (!yigin.isEmpty() && yigin.peek() <= dizi[i]) yigin.pop(); sonuc[i] = yigin.isEmpty() ? -1 : yigin.peek(); yigin.push(dizi[i]); }
Cevabı göster
| i | dizi[i] | pop edilenler | sonuc[i] | yığın (alt→üst) |
|---|---|---|---|---|
| 6 | 1 | — | −1 | 1 |
| 5 | 7 | 1 | −1 | 7 |
| 4 | 5 | — | 7 | 7 5 |
| 3 | 5 | 5 (≤ 5) | 7 | 7 5 |
| 2 | 9 | 5, 7 | −1 | 9 |
| 1 | 2 | — | 9 | 9 2 |
| 0 | 6 | 2 | 9 | 9 6 |
Sonuç: [9, 9, −1, 7, 7, −1, −1]. Yığın alttan üste azalan kalır (monoton yığın). Her öğe en fazla bir kez push ve bir kez pop edilir → O(n) (kaba kuvvet O(n²)).
Klasik Soru · Yığın Uygulamaları
Soru 12: getMin O(1) Olan Yığın
Sırayla push(4), push(6), push(2), push(2), pop(), getMin(), pop(), getMin() yapılıyor. İki getMin() çağrısı ne döndürür ve en sonda min yığınında ne kalır?
void push(int x) { y.push(x); if (min.isEmpty() || x <= min.peek()) min.push(x); } int pop() { int x = y.pop(); if (x == min.peek()) min.pop(); return x; } int getMin() { return min.peek(); }
Cevabı göster
- push'lardan sonra y (alt→üst): 4 6 2 2; min: 4 2 2 (6 > 4 olduğu için eklenmez; ikinci 2,
<=sayesinde eklenir). - pop() → 2; 2 == min.peek() → min: 4 2. getMin() → 2.
- pop() → 2; min: 4. getMin() → 4.
Sonda min yığını: 4. getMin yalnızca peek yapar → O(1).
< yazılsaydı ikinci 2 min'e eklenmez, ilk pop'ta min'deki tek 2 de atılır ve ilk getMin() yanlışlıkla 4 döndürürdü (yığında hâlâ bir 2 vardır).
Adım Adım Çalıştırma · Hanoi ve Stock Span
Soru 13: Stock Span İzleme
span({30, 20, 25, 10, 15, 40}) hangi diziyi döndürür?
İlk gün: indis 0 yığına, span 1. Yığında henüz aşılmamış günlerin indisleri tutulur.
20 ≥ fiyatlar[0] = 30? Hayır → span = 1 − 0 = 1; push(1).
25 ≥ fiyatlar[1] = 20 → pop(1). 1. gün artık kimsenin sınırı olamaz.
25 < 30 → durur. span = 2 − 0 = 2; push(2).
10 < 25 → span = 3 − 2 = 1; push(3).
15 ≥ fiyatlar[3] = 10 → pop(3).
15 < 25 → span = 4 − 2 = 2; push(4).
40 ≥ 15 → pop(4); 40 ≥ 25 → pop(2).
40 ≥ 30 → pop(0). Yığın boşaldı: 40 tüm önceki fiyatları aştı.
Yığın boş → span = i + 1 = 6; push(5).
Her indis bir kez push, en çok bir kez pop edilir → O(n).
int[] span(int[] fiyatlar) { int[] sicrama = new int[fiyatlar.length]; Deque<Integer> yigin = new ArrayDeque<>(); yigin.push(0); sicrama[0] = 1; for (int i = 1; i < fiyatlar.length; i++) { while (!yigin.isEmpty() && fiyatlar[i] >= fiyatlar[yigin.peek()]) yigin.pop(); sicrama[i] = yigin.isEmpty() ? i + 1 : i - yigin.peek(); yigin.push(i); } return sicrama; }
Çoktan Seçmeli · İfade Gösterimleri
Soru 14: Sağdan Birleşen Üs
^ (üs) en yüksek önceliklidir ve sağdan sola birleşir. A ^ B ^ C * D ifadesinin postfix karşılığı hangisidir?
C: Sağdan birleşme (A ^ (B ^ C)) * D demektir. A seçeneği (A ^ B) ^ C'yi, yani soldan birleşmeyi yansıtır. Algoritmada bu yüzden ^ geldiğinde üstteki eşit öncelikli ^ çıkarılmaz; yalnızca önceliği daha büyük olanlar çıkarılır.
Adım Adım Çalıştırma · İfade Gösterimleri
Soru 15: Infix → Postfix İzleme
infixToPostfix("A-B*(C+D)/E") hangi diziyi döndürür?
Öncelik: + − → 1, * / → 2, ( → 0.
İşlenen → doğrudan çıktıya.
Yığın boş → push(−).
İşlenen → çıktıya.
Üstteki − (1) ≥ * (2)? Hayır → push(*).
( her zaman yığına.
İşlenen → çıktıya.
Üstte ( (öncelik 0) → hiçbir şey çıkmaz, push(+).
İşlenen → çıktıya.
) → ( görülene kadar pop: + çıktıya.
( atılır; parantezler çıktıya yazılmaz.
Üstteki * (2) ≥ / (2) → * çıktıya (soldan birleşme).
Üstteki − (1) ≥ 2? Hayır → push(/).
İşlenen → çıktıya.
Girdi bitti: önce /, sonra − çıktıya. Sonuç: A B C D + * E / −. O(n).
for (char c : ifade.toCharArray()) { if (Character.isLetterOrDigit(c)) cikti.append(c); else if (c == '(') yigin.push(c); else if (c == ')') { while (yigin.peek() != '(') cikti.append(yigin.pop()); yigin.pop(); // '(' atılır } else { // operatör while (!yigin.isEmpty() && oncelik(yigin.peek()) >= oncelik(c)) cikti.append(yigin.pop()); yigin.push(c); } } while (!yigin.isEmpty()) cikti.append(yigin.pop());
Klasik Soru · İfade Gösterimleri
Soru 16: Postfix Değerlendirme
postfixDegerlendir("623+*84/-") çağrısının sonucunu bulun; her simgeden sonra işlenen yığınının durumunu yazın.
Cevabı göster
| Okunan | İşlem | Yığın (alt→üst) |
|---|---|---|
| 6, 2, 3 | 3 × push | 6 2 3 |
| + | sag = 3, sol = 2 → 2 + 3 = 5 | 6 5 |
| * | sag = 5, sol = 6 → 6 · 5 = 30 | 30 |
| 8, 4 | 2 × push | 30 8 4 |
| / | sag = 4, sol = 8 → 8 / 4 = 2 | 30 2 |
| − | sag = 2, sol = 30 → 30 − 2 = 28 | 28 |
Sonuç: 28 (infix karşılığı 6 * (2 + 3) − 8 / 4). Sonda yığında tek değer kalır. Parantez ve öncelik gerekmez; her simge bir kez işlenir → O(n).
Çoktan Seçmeli · İfade Gösterimleri
Soru 17: İşlenen Sırası
Dersteki postfixDegerlendir("82/3-") çağrısı hangi değeri döndürür?
if (Character.isDigit(c)) { yigin.push(c - '0'); } else { int sag = yigin.pop(); int sol = yigin.pop(); yigin.push(hesapla(sol, c, sag)); }
D: / için önce sag = 2, sonra sol = 8 çıkar → 8 / 2 = 4; − için sag = 3, sol = 4 → 4 − 3 = 1. A (3), işlenen sırası karıştırılınca çıkar: 2 / 8 = 0 (tam sayı bölmesi), sonra 3 − 0 = 3. İlk pop sağ, ikinci pop sol işlenendir.
Çoktan Seçmeli · Özet
Soru 18: Yazdırma Sırası
Aşağıdaki kodun çıktısı nedir?
Stack<Integer> s = new Stack<>(); Deque<Integer> d = new ArrayDeque<>(); for (int i = 1; i <= 3; i++) { s.push(i); d.push(i); } System.out.println(s + " " + d);
A: Eski Stack (Vector tabanlı) alttan üste, ArrayDeque ise üstten alta (push başa ekler) yazdırır ve gezinir. İki yığın aynı içeriğe sahip olsa da çıktılar ters görünür; for-each ile gezinirken de aynı fark vardır.