Bölüm 8: Yığın ve Kuyruk Uygulamaları
Çoktan Seçmeli · Labirent
Soru 1: Hareket Tablosu
Yön 0 kuzey olmak üzere yönler saat yönünde numaralanıyor: hareket[5] = {1, -1} (dikey, yatay). (3, 4) hücresinden yön 5 ile hangi hücreye gidilir ve bu yönün adı nedir?
C: Yeni konum [i + dikey][j + yatay] = [3 + 1][4 − 1] = (4, 3). Dikey +1 bir satır aşağı (güney), yatay −1 bir sütun sola (batı) demektir. Yön 1 kuzeydoğu, 3 güneydoğu, 7 kuzeybatıdır.
Adım Adım Çalıştırma · Labirent
Soru 2: Küçük Labirentte izbul
Çevresi 1 ile çevrili 6×6 labirentte giriş (1, 1), çıkış (4, 4). izbul hangi yolu bulur, nerede geri adım atar?
Yığında (satır, sütun, yön) = (1, 1, 1); gezildi[1][1] = 1. Çıkış (4, 4).
pop: (1, 1)'den yön 1 ile devam edilir.
Yön 1 (0, 2) duvar; yön 2 (D) (1, 2) açık. Dönüşte yön 3'ten sürmek üzere (1, 1, 3) push.
(1, 2)'den yön 0–3 duvar; yön 4 (G) (2, 2) açık → (1, 2, 5) push.
(2, 2)'den yön 0 gezilmiş, 1 ve 2 duvar; yön 3 (GD) (3, 3) açık → (2, 2, 4) push.
(3, 3)'ten yön 0 duvar; yön 1 (KD) (2, 4) açık → (3, 3, 2) push.
(2, 4) çıkmaz: sekiz yönün hepsi duvar ya da gezilmiş, yon 8 olur ve iç döngü biter.
Geri adım: pop ile (3, 3)'e dönülür ve yön 2'den denemeye devam edilir.
Yön 2 (3, 4) duvar; yön 3 (GD) (4, 4) çıkış. Yol: yığındaki üç kayıt + (3, 3) + çıkış.
while (top > -1 && !bulundu) { konum = yigit_al(&top); satir = konum.satir; sutun = konum.sutun; yon = konum.yon; while (yon < 8 && !bulundu) { ys = satir + hareket[yon].dikey; yy = sutun + hareket[yon].yatay; if (ys == CIKIS_SATIR && yy == CIKIS_SUTUN) bulundu = TRUE; else if (!labirent[ys][yy] && !gezildi[ys][yy]) { gezildi[ys][yy] = 1; konum = (element){satir, sutun, ++yon}; yigit_ekle(&top, konum); satir = ys; sutun = yy; yon = 0; } else ++yon; } }
Çoktan Seçmeli · İfade Gösterimleri
Soru 3: Infix'ten Postfix'e
a - b * c / (d + e) ifadesinin postfix (sonek) karşılığı hangisidir?
B: Tam parantezleme: (a − ((b * c) / (d + e))). * ve / eşit öncelikli ve soldan birleşir: önce b * c, sonra bölme; çıkarma en son. A, a − b'yi önce yapar; C parantezi yok sayar; D çıkarmayı bölmeden önce uygular.
Klasik Soru · İfade Gösterimleri
Soru 4: Elle Önek ve Sonek
a * (b - c) / d + e ifadesini tam parantezleyin; prefix (önek) ve postfix (sonek) karşılıklarını yazın. a = 6, b = 5, c = 2, d = 9, e = 4 için değer nedir?
Cevabı göster
Tam parantezleme: (((a * (b − c)) / d) + e)
- İşleçler sağ kapanışa taşınır → postfix:
a b c - * d / e + - İşleçler sol açılışa taşınır → prefix:
+ / * a - b c d e
Değer: 6 · (5 − 2) = 18, 18 / 9 = 2, 2 + 4 = 6. İşlenenlerin sırası üç gösterimde de aynıdır (a b c d e); yalnız işleçlerin yeri değişir.
Çoktan Seçmeli · İfade Gösterimleri
Soru 5: Postfix'ten Infix'e
a b c * + d - postfix ifadesinin tam parantezli infix karşılığı hangisidir?
D: Yığınla: a, b, c girer; * → (b * c); + → (a + (b * c)); d girer; − → ((a + (b * c)) − d). İşleç geldiğinde ilk çekilen sağ işlenendir. A, + ile *'ın sırasını karıştırır.
Adım Adım Çalıştırma · Postfix Hesaplama
Soru 6: eval("84-2*93/+")
eval("84-2*93/+") çağrısında işlenen yığını nasıl değişir ve hangi değer döner?
İfade 84-2*93/+; yığın boş.
'8' işlenen: '8' − '0' = 8 yığına.
'4' işlenen: '4' − '0' = 4 yığına.
'-' işleç: op1 = 8, op2 = 4 → 8 − 4 = 4 yığına.
'2' işlenen: '2' − '0' = 2 yığına.
'*' işleç: op1 = 4, op2 = 2 → 4 · 2 = 8 yığına.
'9' işlenen: '9' − '0' = 9 yığına.
'3' işlenen: '3' − '0' = 3 yığına.
'/' işleç: op1 = 9, op2 = 3 → 9 / 3 = 3 yığına.
'+' işleç: op1 = 8, op2 = 3 → 8 + 3 = 11 yığına.
'\0': döngü biter; yığında kalan tek değer 11 döner. Yığın en çok 3 değer tuttu.
float eval(const char *expr) { float y[MAX], op1, op2; int top = -1; for (int n = 0; expr[n] != '\0'; n++) { char c = expr[n]; if (isdigit(c)) y[++top] = c - '0'; else { op2 = y[top--]; op1 = y[top--]; y[++top] = islem(c, op1, op2); } } /* sonda tek öğe kalmalı */ return y[top]; }
Çoktan Seçmeli · Postfix Hesaplama
Soru 7: float mı, int mi?
eval yordamının yığını float yerine int dizisi olsaydı eval("72/3*") ne döndürürdü? Dersteki float sürümü ne döndürür?
A: int sürümde 7 / 2 tam sayı bölmesidir: 3, sonra 3 · 3 = 9. float sürümde 7 / 2 = 3.5, 3.5 · 3 = 10.5 (ikisi de çalıştırılarak doğrulandı). D, 10.5'in yuvarlandığını varsayar; C'de int bölme sıfıra doğru keser, sonuç hiç kesirli olmaz.
Klasik Soru · Postfix Hesaplama
Soru 8: Çok Basamaklı Postfix
Dersteki eval yalnız tek basamaklı işlenen okur. İşlenenleri boşlukla ayrılmış, çok basamaklı olabilen postfix ifadeyi (ör. "12 3 - 4 *" → 36) hesaplayan double eval2(const char *e) yordamını yazın; eksik ya da fazla işlenende NAN döndürsün.
Cevabı göster
double eval2(const char *e) { double y[MAX], a, b; int top = -1; while (*e) { if (isspace(*e)) { e++; continue; } if (isdigit(*e)) { double v = 0; while (isdigit(*e)) v = v * 10 + (*e++ - '0'); y[++top] = v; continue; } if (top < 1) return NAN; /* eksik işlenen */ b = y[top--]; a = y[top--]; switch (*e++) { case '+': y[++top] = a + b; break; case '-': y[++top] = a - b; break; case '*': y[++top] = a * b; break; default: y[++top] = a / b; } } return top == 0 ? y[0] : NAN; /* NAN: math.h */ }
Rakamlar v = v * 10 + rakam ile tek sayıya toplanır. Denemeler: "100 25 / 7 +" → 11; "5 +" ve "2 3" → NAN.
Adım Adım Çalıştırma · Infix → Postfix
Soru 9: a-b+c*(d-e) Çevirisi
postfix("a-b+c*(d-e)", cikti) çağrısında işleç yığını nasıl değişir ve sonuç nedir?
Yığının dibinde # (isp = −1) durur; döngüyü o durdurur.
a işlenen → çıktıya.
- : isp(#) = −1 < icp(-) = 12 → yığına.
b → çıktıya.
+ : isp(-) = 12 ≥ icp(+) = 12 → - çıktıya (soldan birleşme); + yığına.
c → çıktıya.
* : isp(+) = 12 < icp(*) = 13 → * üste biner.
( : icp 20 en yüksek; hiçbir şey çıkmadan girer.
d → çıktıya.
- : isp(() = 0 < 12 → yığına; yığındaki ( en düşük önceliklidir.
e → çıktıya.
) : ( görülene kadar al → - çıktıya; ( atılır.
Girdi bitti: önce *, sonra + çıktıya. Sonuç ab-cde-*+.
void postfix(const char *e, char *cikti) { char y[MAX] = {'#'}; int top = 0, k = 0; for (; *e; e++) { if (isalnum(*e)) cikti[k++] = *e; else if (*e == ')') { while (y[top] != '(') cikti[k++] = y[top--]; top--; /* '(' at */ } else { while (isp(y[top]) >= icp(*e)) cikti[k++] = y[top--]; y[++top] = *e; } } while (top > 0) cikti[k++] = y[top--]; cikti[k] = '\0'; }
Çoktan Seçmeli · Infix → Postfix
Soru 10: Gelen İşleç Neleri Çıkarır?
a + b * c - d çevrilirken - okunduğu anda yığında (alttan üste) # + * vardır. Bu adımda yığından çıktıya hangi işleçler alınır?
C: isp(*) = 13 ≥ icp(-) = 12 → * çıkar; isp(+) = 12 ≥ 12 → + de çıkar; isp(#) = −1'de durulur, sonra - yığına girer. Eşitlikte çıkarmak soldan birleşmeyi sağlar: (a + b * c) − d. Sonuç abc*+d-.
Klasik Soru · Infix → Postfix
Soru 11: Ters Çevirerek Önek
a - b / c + d ifadesini “ters çevir, postfix'e çevir, yine ters çevir” yöntemiyle prefix'e çevirin. Ara sonuçları yazın; eşit öncelikte neden > kullanılır?
Cevabı göster
- Ters çevirme (parantez yok):
d + c / b - a - Postfix'e çevirme, eşit öncelikte yığından almadan (
>):d c b / a - + - Yine ters çevirme:
+ - a / b c d
Doğrulama: + (− a (/ b c)) d = ((a − (b / c)) + d). Ters çevrilmiş ifadede soldan birleşme sağdan birleşmeye döner; >= kullanılsaydı a − (… + d) gibi yanlış gruplanırdı.
Çoktan Seçmeli · Infix → Postfix
Soru 12: Önek Hesaplamada Sıra
prefix_eval("-/82*13") ne döndürür? Yordam ifadeyi sağdan sola tarar; işleçte ilk çekilen değer sol işlenendir.
B: Sağdan sola: 3, 1 girer; * → 1 · 3 = 3; 2, 8 girer; / → op1 = 8, op2 = 2 → 4; − → op1 = 4, op2 = 3 → 1. A (2.75), postfix'teki sırayı kullanmanın sonucudur: 2 / 8 = 0.25, 3 − 0.25 = 2.75 (ikisi de çalıştırıldı).
Klasik Soru · Diğer Uygulamalar
Soru 13: Sayaçla Parantez Denetimi
Yığın yerine tek sayaç kullanan bu sürüm hangi hatalı girdileri dengeli sayar? İki örnek verin ve düzeltmeyi açıklayın.
bool dengeli(const char *e) { int acik = 0; for (; *e; e++) { if (*e=='(' || *e=='[' || *e=='{') acik++; else if (*e==')' || *e==']' || *e=='}') acik--; } return acik == 0; }
Cevabı göster
"([)]": sayaç 1, 2, 1, 0 → true. Oysa ] gelince üstte ( vardır: yanlış eşleşme.")(": sayaç −1, 0 → true. Kapanan, açılandan önce gelmiştir."(a]"de true döner: tür hiç karşılaştırılmaz.
Tek tür parantezde if (--acik < 0) return false; eklemek yeter. Birden çok türde “en son açılan” bilgisi gerekir: açanlar yığına konur, kapanan üstle eşleşmeli (dersteki dengeli). Hepsi çalıştırılarak denendi.
Çoktan Seçmeli · Diğer Uygulamalar
Soru 14: Geri Al ve Yinele
Düzenleyici iki yığın kullanıyor: her yeni işlem “geri al” yığınına girer ve “yinele” yığınını boşaltır. Boş metne sırayla A yaz, B yaz, C yaz, geri al, geri al, D yaz, yinele uygulanıyor. Metin ne olur?
A: İki geri alma C'yi ve B'yi yinele yığınına taşır (metin A). D yazmak yeni bir işlemdir: yinele yığını boşalır, metin AD olur. Son yinele'nin yapacak işi kalmamıştır. B, yinele yığınının boşaltılmadığını varsayar.
Klasik Soru · Özet
Soru 15: Yığın mı Kuyruk mu: Yol Uzunluğu
Giriş (1, 1), çıkış (4, 4) olan yandaki labirentte (koyu hücreler duvar) aynı sekiz yön ve aynı sırayla kuyruklu arama (BFS) yapılsaydı bulunan yol kaç hücre olurdu? izbul'un yolu neden daha uzundur? Yığınlı aramada yığın en çok kaç kayıt tutar?
Cevabı göster
BFS hücreleri girişe uzaklık sırasıyla açar: (1, 1)'in komşusu (2, 2) çaprazdan doğrudan açılır, sonra (3, 3), sonra çıkış. Yol 4 hücre: (1, 1) → (2, 2) → (3, 3) → (4, 4).
izbul derinlik önceliklidir: yön 2 (D) yön 3'ten (GD) önce denendiği için önce (1, 2)'ye girer ve oradan devam eder; yolu 5 hücredir ve (2, 4) çıkmazına da uğrar. Yığın en çok 4 kayıt tuttu (çıkmazdayken). İki arama da O(m·p) zaman alır; yalnız BFS en kısa yolu garanti eder (C ile doğrulandı).
Çoktan Seçmeli · Özet
Soru 16: İşleç Yığınının Boyu
Uzunluğu n olan bir infix ifade postfix'e çevrilirken işleç yığınında aynı anda en çok kaç simge bulunabilir?
D: Her simge yığına en çok bir kez girip bir kez çıkar: zaman O(n). Ama ((((a + b) … gibi bir girdide bütün açılan parantezler aynı anda yığındadır; önceliği artan işleç dizileri de (a + b * c …) yığında birikir. Ek bellek en kötü O(n)'dir.