Bölüm 7: Yığın

Bölüm 7: Yığın · Çalışma Soruları
Yığın ADT ve LIFODizi ve bağlı liste ile gerçeklemeAmortize analizYığın uygulamalarıHanoi ve stock spanInfix, postfix, prefix
Sercan KÜLCÜ

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.123456–89
büyütme—1→22→4—4→8—8→16
kopya0120408

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İşlemYığı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
idizi[i]pop edilenlersonuc[i]yığın (alt→üst)
61—−11
571−17
45—77 5
355 (≤ 5)77 5
295, 7−19
12—99 2
06299 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İşlemYığın (alt→üst)
6, 2, 33 × push6 2 3
+sag = 3, sol = 2 → 2 + 3 = 56 5
*sag = 5, sol = 6 → 6 · 5 = 3030
8, 42 × push30 8 4
/sag = 4, sol = 8 → 8 / 4 = 230 2
−sag = 2, sol = 30 → 30 − 2 = 2828

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.

Son

Bölüm 7: Yığın: Çalışma Soruları
Konu anlatımı: Yığın sunumu
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.