Bölüm 4: Yığın
Klasik Soru · Yığın
Soru 1: Stack Çıktısı
Programın çıktısı nedir?
Stack<Integer> s = new Stack<>();
s.push(4); s.push(8); s.push(15);
System.out.print(s.pop() + " ");
s.push(16); s.push(23);
System.out.print(s.peek() + " ");
System.out.print(s.search(8) + " ");
System.out.print(s.pop() + s.pop() + " ");
System.out.print(s + " ");
s.clear();
System.out.print(s.empty() + " ");
s.pop();Cevabı göster
Çıktı: 15 23 3 39 [4, 8] true ve ardından EmptyStackException.
pop()→ 15; yığın [4, 8].- 16, 23 eklenir: [4, 8, 16, 23];
peek()→ 23 (çıkarmaz). search(8): tepeden 1'den başlayarak uzaklık: 23→1, 16→2, 8→3.s.pop() + s.pop()önce tam sayı toplamıdır: 23 + 16 = 39.toStringalttan üste yazar: [4, 8].clear()sonrası boş yığındapop()istisna fırlatır.
Klasik Soru · Yığın
Soru 2: Bağlı Liste ile Yığın
Bağlı liste kullanan yığın sınıfının push, pop ve peek metotlarını yazınız. Hepsinin O(1) olması için ekleme/çıkarma listenin hangi ucundan yapılmalıdır?
public class BagliYigin { private Dugum tepe; // baş private int boyut; // push, pop, peek ? }
Cevabı göster
public void push(int x) { Dugum yeni = new Dugum(x); yeni.sonraki = tepe; tepe = yeni; boyut++; } public int pop() { int x = peek(); // boşsa hata tepe = tepe.sonraki; boyut--; return x; } public int peek() { if (tepe == null) throw new RuntimeException("Yığın boş"); return tepe.veri; }
İşlemler listenin başından yapılmalıdır; sondan çıkarmada yeni sonu bulmak O(n) olurdu. Kapasite sınırı yoktur.
Klasik Soru · Yığın
Soru 3: Infix, Postfix ve Prefix
(a) A * (B + C) - D / E ifadesini postfix ve prefix biçimine çeviriniz.
(b) 6 2 3 + * 8 4 / - postfix ifadesini yığınla değerlendiriniz; her adımda yığının durumunu yazınız.
Cevabı göster
(a) Postfix: A B C + * D E / -
Prefix: - * A + B C / D E
| Okunan | İşlem | Yığın (alt → üst) |
|---|---|---|
| 6, 2, 3 | push | 6 2 3 |
| + | 2 + 3 = 5 | 6 5 |
| * | 6 × 5 = 30 | 30 |
| 8, 4 | push | 30 8 4 |
| / | 8 / 4 = 2 | 30 2 |
| − | 30 − 2 = 28 | 28 |
(b) Sonuç: 28. Operatör geldiğinde önce çekilen eleman sağ işlenendir.
Klasik Soru · Yığın
Soru 4: Parantez Dengesi
Yığın tabanlı parantez denetimi algoritmasını { ( [ ] ) ( } ve [ ( ) { } ] girdileri için adım adım uygulayınız. Hangisi geçerlidir? Algoritmanın karmaşıklığı nedir?
Cevabı göster
| Karakter | İşlem | Yığın |
|---|---|---|
| { | push | { |
| ( | push | { ( |
| [ | push | { ( [ |
| ] | pop [ ✓ | { ( |
| ) | pop ( ✓ | { |
| ( | push | { ( |
| } | üstte ( var ✗ | — |
{ ( [ ] ) ( } geçersiz: } gelince tepede ( var.
[ ( ) { } ] geçerli: her kapanış tepedeki açılışla eşleşir ve sonunda yığın boş kalır.
Kurallar: açılışta push; kapanışta yığın boşsa ya da tepe eşleşmiyorsa hata; sonda yığın boş değilse hata. Zaman O(n), bellek O(n).
Klasik Soru · Yığın
Soru 5: İki Yığınla Kuyruk
Yalnızca iki yığın (s1, s2) kullanarak FIFO çalışan bir kuyruk tasarlayınız: ekle(x) ve cikar(). Sırasıyla ekle(1), ekle(2), ekle(3), cikar(), ekle(4), cikar(), cikar() için çıktılar nedir?
Cevabı göster
void ekle(int x) { s1.push(x); } int cikar() { if (s2.isEmpty()) while (!s1.isEmpty()) s2.push(s1.pop()); // ters çevir return s2.pop(); }
ekle 1, 2, 3 → s1 = [1, 2, 3]. İlk cikar: s2 boş → aktarım, s2 = [3, 2, 1] → 1.
ekle(4) → s1 = [4]. cikar → s2'den 2, cikar → 3.
Her eleman en fazla bir kez s1'den s2'ye taşındığı için işlem başına amortize O(1). Yığın tek başına kuyruğun yerine kullanılamaz ama iki yığın FIFO davranışını taklit edebilir.
Çoktan Seçmeli · Yığın
Test 1
Boş yığına sırasıyla push(1), push(2), push(3), pop(), push(4), pop(), pop() uygulanıyor. Yığında ne kalır?
pop'lar sırasıyla 3, 4, 2 döndürür. Alttaki 1 kalır.
2 3 4 * + postfix ifadesinin değeri nedir?
3 · 4 = 12, sonra 2 + 12 = 14. Operatör, yığının üstündeki iki değere uygulanır.
Çoktan Seçmeli · Yığın
Test 2
1, 2, 3 sırayla push ediliyor, araya pop'lar serpiştirilebiliyor. Hangi çıkış sırası imkânsızdır?
3 önce çıkıyorsa 1 ve 2 yığındadır, üstte 2 vardır; 1, 2'den önce çıkamaz.
Dizi tabanlı yığında başlangıçta tepe = -1. Yığın dolu koşulu nedir?
Son geçerli indis kapasite − 1'dir. push: dizi[++tepe] = x.
Adım Adım Çalıştırma · Yığın
Postfix Değerlendirme
4 2 5 * + 6 - ifadesini yığınla değerlendiren kodu adım adım izleyin.
Önce tahmin edin: ifadenin değeri nedir?
Girdi boşluklardan parçalanır, boş yığın oluşturulur.
4 sayıdır → push.
2 sayıdır → push.
5 sayıdır → push.
Operatör: önce b = 5, sonra a = 2 çekilir.
2 * 5 = 10 sonucu push edilir.
Operatör: önce b = 10, sonra a = 4 çekilir.
4 + 10 = 14 sonucu push edilir.
6 sayıdır → push.
Operatör: önce b = 6, sonra a = 14 çekilir.
14 - 6 = 8 sonucu push edilir.
Sonuç 8. Her simge bir kez işlenir: O(n).
String[] t = "4 2 5 * + 6 -".split(" "); Stack<Integer> s = new Stack<>(); for (String x : t) { if (x.matches("\\d+")) { s.push(Integer.parseInt(x)); } else { int b = s.pop(), a = s.pop(); char c = x.charAt(0); s.push(c == '+' ? a + b : c == '-' ? a - b : a * b); } } System.out.println(s.pop());
Ucu Açık Soru · Yığın
Geri Al ve Yinele
- Bir metin düzenleyicisinde hem geri al (undo) hem yinele (redo) özelliği tasarlayın. Hangi veri yapılarını kullanırsınız? Her işlemde ne olur?
- Kullanıcı geri aldıktan sonra yeni bir şey yazarsa yinele geçmişine ne olmalıdır? Bellek sınırlıysa (son 100 işlem) tasarımınızı nasıl değiştirirsiniz?
Örnek cevap ve değerlendirme ölçütleri
1. İki yığın: geri ve ileri. Her düzenleme işlemi (ne yapıldığı + nasıl tersine çevrileceği) geri'ye push edilir. Undo: geri.pop(), işlemin tersi uygulanır, işlem ileri'ye push edilir. Redo: ileri.pop(), işlem yeniden uygulanır, geri'ye push edilir. Hepsi O(1).
2. Yeni düzenleme yapılınca ileri yığını temizlenir; aksi hâlde artık geçerli olmayan bir geçmiş yinelenir. Bellek sınırında en eski kaydın atılması gerekir; yığın yalnızca tepeden erişir. Bu yüzden iki uçlu kuyruk (Deque) ya da dairesel dizi kullanılır: yeni kayıt tepeye eklenir, kapasite aşılınca alttan silinir.
Değerlendirme: iki yığın modeli · işlem nesnesinin içeriği (ters işlem) · redo geçmişinin temizlenmesi · sınırlı bellek için deque/dairesel yapı.