Bölüm 1: Giriş ve Algoritma Analizi
Çoktan Seçmeli · Temeller
Soru 1: Sonlanmayan Program
İşletim sistemi gibi kapatılana dek çalışmayı sürdüren bir program, algoritma ölçütlerinden hangisini sağlamaz?
C: Algoritma her girdide sonlu adım sonra durmalıdır. İşletim sistemi komutları kesin ve uygulanabilir olabilir, çıktı da üretir; yalnız sona ermediği için algoritma değil, bir hesaplama yöntemidir.
Çoktan Seçmeli · Temeller
Soru 2: Opak Tip
main.c yalnızca kesir.h'yi içeriyor; başlıkta typedef struct kesir Kesir; var, yapının alanları ise kesir.c'de tanımlı. main.c'deki hangi satır derlenmez?
B: main.c için struct kesir eksik (incomplete) bir türdür: işaretçisi tutulabilir, fonksiyonlara geçirilebilir, ama alanına erişilemez ve sizeof alınamaz. Alanların gizlenmesi ADT'nin C'deki karşılığıdır; erişim yalnızca arayüz fonksiyonlarıyla olur. C'deki kesir_sil(NULL) çağrısı free(NULL) yapar; bu zararsızdır.
Hata Bulma · Temeller
Soru 3: Kesir Toplama ve Sızıntı
Sunumdaki kesir gerçeklemesiyle bu parça ne yazdırır? Bellek açısından kusuru nedir, nasıl düzeltilir?
Kesir *a = kesir_olustur(1, 4);
Kesir *b = kesir_olustur(1, 6);
Kesir *t = kesir_topla(a, b);
kesir_yaz(t);
printf("%d\n",
kesir_esit(t, kesir_olustur(5, 12)));
kesir_sil(a); kesir_sil(b);
kesir_sil(t);Cevabı göster
Çıktı: 10/24 ve 1.
kesir_toplasadeleştirmez: pay 1·6 + 1·4 = 10, payda 4·6 = 24.kesir_esitçapraz çarpar: 10·12 = 120 = 5·24 → 1 (eşit).kesir_olustur(5, 12)'nin döndürdüğü kesir hiçbir değişkende tutulmadı, hiçfreeedilmedi: bellek sızıntısı. Sayaçlı sarmalayıcıyla 4malloc, 3freegörülür.
Kesir *u = kesir_olustur(5, 12);
if (t && u)
printf("%d\n", kesir_esit(t, u));
kesir_sil(u);Her olustur/topla sonucu çağırana aittir; bırakmak da onun işidir.
Çoktan Seçmeli · Seçimli Sıralama
Soru 4: İki Turdan Sonra
Seçimli sıralama (sort) {5, 1, 4, 2, 3} dizisine uygulanıyor. Dış döngünün ilk iki turu (i = 0 ve i = 1) bittiğinde dizi nasıl görünür?
D: i = 0'da en küçük 1 (indis 1) bulunur, 5 ile takas edilir: {1, 5, 4, 2, 3}. i = 1'de kalan kısmın en küçüğü 2 (indis 3) bulunur, list[1] = 5 ile takas edilir: {1, 2, 4, 5, 3}. Takas yalnızca iki hücrenin yerini değiştirir; aradaki 4 yerinde kalır, A bunu kaydırma sanır.
Çıktı Sorusu · Seçimli Sıralama
Soru 5: Yan Etkili Makro Argümanı
Sunumdaki üç argümanlı SWAP makrosuyla bu parça ne yazdırır? Takas gerçekleşti mi?
#define SWAP(x, y, t) \ ((t) = (x), (x) = (y), (y) = (t)) int a[] = {7, 8, 9}, i = 0, j = 2, t; SWAP(a[i++], a[j], t); printf("%d %d %d i=%d\n", a[0], a[1], a[2], i);
Cevabı göster
Çıktı: 7 9 7 i=2.
Önişlemci metni yerine koyar: ((t) = (a[i++]), (a[i++]) = (a[j]), (a[j]) = (t)). i++ iki kez değerlendirilir:
t = a[0]→ 7, i = 1.a[1] = a[2]→ 9, i = 2.a[2] = t→ 7.
Virgül işleci her adımı sıraya koyduğu için sonuç tanımlıdır, ama takas yanlış hücrelerde yapıldı: 8 kayboldu. Yan etkili argüman makroya verilmez; swap(&a[i], &a[j]); i++; yazılır.
Adım Adım Çalıştırma · Seçimli Sıralama
Soru 6: Seçimli Sıralamayı İzlemek
sort({4, 2, 5, 1}, 4) çağrısında her turdan sonra dizi ne olur? Toplam kaç karşılaştırma ve kaç gerçek takas (i ≠ min) yapılır?
Başlangıç. Dış döngü n − 1 = 3 tur döner.
i = 0: j = 1, 2, 3 için 3 karşılaştırma. 2 < 4 → min = 1; 1 < 2 → min = 3.
list[0] ↔ list[3]: 1 başa gelir.
i = 1: 2 karşılaştırma (5 ve 4, 2'den küçük değil). min = i kalır; SWAP hücreyi kendisiyle takas eder, gerçek takas sayılmaz.
i = 2: tek karşılaştırma, 4 < 5 → min = 3.
list[2] ↔ list[3].
i = 3 = n − 1 → döngü biter. Karşılaştırma 3 + 2 + 1 = 6 = n(n−1)/2; takas 2 (en çok n − 1).
void sort(int list[], int n) { int i, j, min, temp; for (i = 0; i < n - 1; i++) { min = i; for (j = i + 1; j < n; j++) if (list[j] < list[min]) min = j; SWAP(list[i], list[min], temp); } }
Çoktan Seçmeli · Performans Analizi
Soru 7: Adım Sayısı
Sunumdaki kurala göre (atama, her for testi, gövde ve return birer adım; bildirimler 0) aşağıdaki fonksiyon n = 7 için kaç program adımı atar?
float ort(float a[], int n) { float s = 0; int i; for (i = 0; i < n; i += 2) s += a[i]; return s; }
B: i = 0, 2, 4, 6 için gövde 4 kez çalışır, for testi 5 kez (son test i = 8'de yanlış) yapılır. 1 (s = 0) + 5 + 4 + 1 (return) = 11. Genel olarak 2⌈n/2⌉ + 3 adım: yine O(n). 17 = 2n + 3, döngünün ikişer arttığını gözden kaçırır.
Çoktan Seçmeli · Performans Analizi
Soru 8: rsum'un Yığın Derinliği
rsum(list, 1000) çağrıldığında en derin anda yığında kaç rsum çerçevesi aynı anda bulunur?
A: rsum(list, 1000) → rsum(list, 999) → … → rsum(list, 0): n + 1 = 1001 çağrı iç içedir ve rsum(list, 0) çalışırken hiçbiri dönmemiştir. Bu yüzden Srsum(n) n ile doğrusal büyür; döngülü sum ise tek çerçeveyle O(1) ek bellek kullanır.
Klasik Soru · Performans Analizi
Soru 9: İki Katına Çıkan Sayaç
Aşağıdaki parçada x++ n = 16 ve n = 20 için kaç kez işletilir? Parçanın zaman karmaşıklığı nedir?
x = 0; for (i = 1; i <= n; i *= 2) for (j = 0; j < i; j++) x++;
Cevabı göster
Dış döngü i = 1, 2, 4, 8, 16 değerlerini alır (iki örnekte de 32 > n). İç döngü i kez döner:
1 + 2 + 4 + 8 + 16 = 31 (n = 16 için de, n = 20 için de).
Genel olarak k = ⌊lg n⌋ ise toplam 2k+1 − 1 < 2n'dir. İç içe iki döngü olmasına rağmen parça O(n)'dir; dış döngünün lg n tur dönmesi O(n log n) sonucunu vermez, çünkü iç döngü uzunlukları geometrik dizi oluşturur.
Çoktan Seçmeli · Asimptotik Gösterim
Soru 10: Yanlış Olan İfade
Aşağıdaki ifadelerden hangisi yanlıştır?
D: n²/(n·lg n) = n/lg n sınırsız büyür; hiçbir c için n² ≤ c·n·lg n her büyük n'de sağlanmaz. A doğrudur ama bilgi vermez (sıkı sınır Θ(n)); B seçimli sıralamanın karşılaştırma sayısıdır; C'de n ≥ 2 için 10n·lg n ≥ n.
Klasik Soru · Asimptotik Gösterim
Soru 11: c ve n₀ Bulmak
f(n) = 2n² + 9n + 4 veriliyor. c = 3 seçilirse f(n) ≤ c·n² eşitsizliği hangi n₀'dan sonra hep sağlanır? f(n) = Θ(n²) olduğunu da gösteriniz.
Cevabı göster
2n² + 9n + 4 ≤ 3n² ⇔ n² − 9n − 4 ≥ 0. Kök (9 + √97)/2 ≈ 9,42 olduğundan en küçük tam sayı n₀ = 10:
| n | 9 | 10 | 11 |
|---|---|---|---|
| f(n) | 247 | 294 | 345 |
| 3n² | 243 | 300 | 363 |
Alt sınır: her n ≥ 1 için f(n) ≥ 2n² → Ω(n²), c₁ = 2. İkisi birlikte: 2n² ≤ f(n) ≤ 3n² (n ≥ 10) → Θ(n²). c büyütülürse n₀ küçülür: c = 15 için n₀ = 1 yeter.
Çoktan Seçmeli · Asimptotik Gösterim
Soru 12: Üstel Büyüme
Adım sayısı 2ⁿ ile orantılı bir algoritma bir makinede n = 30 için 1 saniye sürüyor. Aynı makinede n = 40 için yaklaşık ne kadar sürer?
C: 2⁴⁰ / 2³⁰ = 2¹⁰ = 1024 kat → 1024 sn ≈ 17 dk. A doğrusal (40/30), B kübik ((40/30)³) büyüme varsayar; D, 2²⁰ sn'dir. n'ye 10 eklemek süreyi bin katına çıkarır: daha hızlı makine bu farkı kapatamaz.
Hata Bulma · Performans Ölçümü
Soru 13: Bekçinin Yeri
Sunumdaki bekçili seqsearch aşağıdaki gibi çağrılıyor. 9 arandığında kaç karşılaştırma (list[i] != searchnum) yapılır? 7 aranınca ne olur? Koddaki hata nedir?
int seqsearch(int list[], int searchnum, int n) { int i; list[n] = searchnum; /* bekci */ for (i = 0; list[i] != searchnum; i++) ; return (i < n) ? i : -1; } /* main: */ int a[5] = {4, 8, 2, 9, 5}; seqsearch(a, 9, 5); seqsearch(a, 7, 5);
Cevabı göster
- 9 için: 4 ≠ 9, 8 ≠ 9, 2 ≠ 9, 9 = 9 → 4 karşılaştırma, dönen 3.
- 7 için: bekçi
list[5] = 7yazılır; 5 hücre + bekçi = 6 karşılaştırma (n + 1), i = 5 → −1.
Sınır hatası: a yalnızca 5 öğeliktir; list[n] = searchnum dizinin dışına, a[5]'e yazar. Bu tanımsız davranıştır: komşu bir değişken bozulabilir. Bekçili aramada dizide n + 1 yer olmalıdır: int a[6] = {4, 8, 2, 9, 5}; (sunumda MAX_SIZE = 5001).
Adım Adım Çalıştırma · Sihirli Kare
Soru 14: Sihirli Kare n = 5
sihirli(5, k) çağrısında 1–8 sayıları hangi hücrelere yazılır? Kare dolduğunda ilk satır nedir?
İlk satırın ortası: j = (5 − 1)/2 = 2 → k[0][2] = 1.
Sol üst çapraz (−1, 1): satır taştı → r = 4. (4, 1) boş → 2 oraya.
(3, 0) boş → 3.
Sütun taştı → c = 4. (2, 4) boş → 4.
(1, 3) boş → 5.
Sol üst çapraz (0, 2) dolu (1 var) → bir aşağı: i = 2, j değişmez → (2, 3) = 6.
(1, 2) boş → 7.
(0, 1) boş → 8.
Döngü s = 25'te biter. İlk satır 15 8 1 24 17; her satır, sütun ve köşegen 5·26/2 = 65. 25 yerleştirme → O(n²).
void sihirli(int n, int k[][MAX]) { int i = 0, j = (n - 1) / 2, s, r, c; k[i][j] = 1; /* k sifirlanmis */ for (s = 2; s <= n * n; s++) { r = (i - 1 < 0) ? n - 1 : i - 1; c = (j - 1 < 0) ? n - 1 : j - 1; if (k[r][c]) i = (i + 1) % n; else { i = r; j = c; } k[i][j] = s; } }
Çoktan Seçmeli · Performans Ölçümü
Soru 15: Sıfır Çıkan Süre
sort çağrısı yaklaşık 0,4 saniye sürüyor ve CLOCKS_PER_SEC 1000. Ölçüm parçası ne yazdırır?
clock_t start = clock(); sort(list, 2000); clock_t stop = clock(); printf("%f\n", (double)((stop - start) / CLOCKS_PER_SEC));
B: clock_t bir tam sayı türüdür; (stop - start) / CLOCKS_PER_SEC önce tam sayı bölmesiyle 400 / 1000 = 0 olur, dönüşüm sonradan yapılır. Doğrusu (double)(stop - start) / CLOCKS_PER_SEC. Kısa işlerde ölçüm yine de birçok tekrarın ortalamasıyla yapılmalıdır.
Kod Yazma · Ödevler
Soru 16: Hızlı Üs Alma
xⁿ değerini (n ≥ 0) özyinelemeli hesaplayan long us(long x, int n) fonksiyonunu, n'yi her çağrıda yarıya indirerek yazınız. us(2, 10) kaç çağrı yapar? Karmaşıklık nedir?
Cevabı göster
long us(long x, int n) { long y; if (n == 0) return 1; /* taban */ y = us(x, n / 2); /* tek çağrı */ return (n % 2) ? y * y * x : y * y; }
us(2, 10) → us(2, 5) → us(2, 2) → us(2, 1) → us(2, 0): 5 çağrı, sonuç 1024.
Her çağrıda n yarıya iner: ⌊lg n⌋ + 2 çağrı → zaman ve yığın O(log n). us(x, n/2) * us(x, n/2) yazılsaydı aynı alt problem iki kez çözülür, çağrı sayısı O(n)'e çıkardı.
Çoktan Seçmeli · Ödevler
Soru 17: komb'un Çağrı Sayısı
Sunumdaki komb fonksiyonu komb(5, 2) için toplam kaç kez çağrılır (ilk çağrı dâhil)?
long komb(int n, int m) { if (m == 0 || m == n) return 1; return komb(n - 1, m) + komb(n - 1, m - 1); }
A: Her yaprak (taban durum) 1 döndürür; sonuç 10 olduğuna göre 10 yaprak vardır. İç düğümlerin her biri tam iki çağrı yaptığından iç düğüm sayısı 9'dur: 10 + 9 = 19 = 2·C(5, 2) − 1. Aynı alt problemler (ör. komb(3, 1)) tekrar tekrar çözülür.
Adım Adım Çalıştırma · Ödevler
Soru 18: fibo(4) Çağrı Ağacı
Ödev çözümündeki fibo ile fibo(4) kaç kez çağrılır ve yığın en çok kaç fibo çerçevesi derinleşir?
n = 4 > 1: önce fibo(3) hesaplanacak (soldaki işlenenin önce çağrıldığı varsayıldı).
fibo(3) de taban durum değil → fibo(2).
fibo(2) → fibo(1).
Taban durum: 1 döner. Yığın en derin hâlinde: 4 fibo çerçevesi.
fibo(0) → 0; fibo(2) = 1 + 0 = 1 döner.
fibo(3)'ün ikinci çağrısı fibo(1) = 1; fibo(3) = 1 + 1 = 2.
fibo(4) sağ işlenene geçer: fibo(2) yeniden hesaplanır.
fibo(1) = 1, fibo(0) = 0 → fibo(2) = 1.
fibo(4) = 2 + 1 = 3. Toplam 9 çağrı, en çok 4 çerçeve. C, + işlenenlerinin hangi sırayla çağrılacağını belirlemez; sayı ve sonuç değişmez.
long fibo(long n) { if (n <= 1) return n; return fibo(n - 1) + fibo(n - 2); } int main(void) { printf("%ld\n", fibo(4)); return 0; }