Bölüm 3: Arama Algoritmaları
Çıktı Sorusu · Doğrusal Arama
Soru 1: Kaç Karşılaştırma?
dizi = {33, 21, 12, 7, 8, 1, 3, 44, 56, 18} (n = 10) için dogrusalArama(dizi, 10, 44) ve dogrusalArama(dizi, 10, 17) ne döndürür? Her birinde dizi[i] != aranan kaç kez değerlendirilir?
int dogrusalArama(int[] dizi, int n, int aranan) { int i = 0; while (i < n && dizi[i] != aranan) i++; if (i < n) return i; else return -1; }
Cevabı göster
- 44: indis 7'de bulunur → 7 döner; i = 0 … 7 için 8 karşılaştırma.
- 17: dizide yok → −1; 10 karşılaştırma. i = 10 olunca
i < nyanlış olur ve kısa devre && sayesindedizi[10]'a erişilmez.
i < n testi ise ayrıca 44 için 8, 17 için 11 kez yapılır. Başarılı aramada ortalama (n + 1)/2 = 5,5 karşılaştırma.
Adım Adım Çalıştırma · Doğrusal Arama
Soru 2: Bekçili Arama
gozcuIleAra(dizi, 5, 7) çağrısı dizi = {12, 5, 9, 20, 7} için çalışıyor. Döngü nerede durur, metot ne döndürür?
Aranan 7, son öğe de 7. sonEleman = 7 saklanır, son hücreye bekçi olarak aranan (7) yazılır; dizi görünürde değişmez.
dizi[0] = 12 ≠ 7 → i = 1. Döngüde yalnızca bir karşılaştırma var; i < n testi yok.
dizi[1] = 5 ≠ 7 → i = 2.
dizi[2] = 9 ≠ 7 → i = 3.
dizi[3] = 20 ≠ 7 → i = 4.
dizi[4] = 7 (bekçi) → döngü durur. Son hücreye sonEleman geri yazılır.
i < n − 1 yanlış (4 < 4), ama sonEleman == aranan doğru → 4 döner. Bu ikinci koşul olmasaydı gerçek son öğe “bulunamadı” sayılırdı. 4 aransaydı aynı döngü i = 4'te durur ve −1 dönerdi.
int gozcuIleAra(int[] dizi, int n, int aranan) { int sonEleman = dizi[n - 1]; dizi[n - 1] = aranan; // bekçi int i = 0; while (dizi[i] != aranan) i++; dizi[n - 1] = sonEleman; // geri koy if (i < n - 1 || sonEleman == aranan) return i; return -1; }
Çıktı Sorusu · İkili Arama
Soru 3: Yazdırılan Orta Öğeler
Dizi [2, 3, 4, 7, 8, 9, 10, 21, 22, 31] iken aranan 40 olursa aşağıdaki kod ekrana ne yazdırır ve ne döndürür?
int baslangic = 0; int bitis = dizi.length - 1; while (baslangic <= bitis) { int orta = baslangic + (bitis - baslangic) / 2; System.out.println(dizi[orta]); if (dizi[orta] == aranan) { return orta; } else if (dizi[orta] > aranan) { bitis = orta - 1; } else { baslangic = orta + 1; } } return -1;
Cevabı göster
Çıktı: 8 21 22 31, dönüş −1.
| baslangic | bitis | orta | dizi[orta] |
|---|---|---|---|
| 0 | 9 | 4 | 8 |
| 5 | 9 | 7 | 21 |
| 8 | 9 | 8 | 22 |
| 9 | 9 | 9 | 31 |
40 tüm öğelerden büyük olduğu için her turda sağa gidilir; baslangic = 10 > bitis = 9 olunca döngü biter. 4 tur = ⌊log₂ 10⌋ + 1 (en kötü durum).
Çoktan Seçmeli · İkili Arama
Soru 4: İki Milyon Öğe
Sıralı 2.000.000 öğeli bir dizide ikili arama en kötü durumda kaç tur (orta karşılaştırması) yapar?
C: En fazla ⌊log₂ n⌋ + 1 tur: 2²⁰ = 1.048.576 ≤ 2.000.000 < 2²¹ → ⌊log₂ n⌋ = 20 → 21 tur. 20, ⌊log₂ n⌋'deki “+ 1” unutulunca çıkar; 1.000.000 doğrusal aramanın ortalamasıdır.
Çoktan Seçmeli · İkili Arama
Soru 5: ±1 Unutulursa
İkili aramada son = orta - 1; yerine son = orta; yazılırsa (döngü koşulu bas <= son) ne olabilir?
C: bas = son = orta iken aranan dizi[orta]'dan küçükse son = orta olur ve aralık hiç değişmez; döngü sonsuza dek döner. Orta öğe zaten denetlendiği için sınırlar ±1 ile güncellenmelidir.
Klasik Soru · İkili Arama
Soru 6: Örtük Arama Ağacı
[4, 9, 13, 20, 26, 31, 40] dizisinde ikili aramanın karşılaştırma ağacını çizin. Hangi öğeler 1, 2 ve 3 karşılaştırmada bulunur? Başarılı aramalarda ortalama kaç karşılaştırma yapılır?
Cevabı göster
Kök ilk orta öğedir (20); sol yarının ortası 9, sağ yarınınki 31; kalanlar yapraktır:
- 1 karşılaştırma: 20 · 2 karşılaştırma: 9, 31 · 3 karşılaştırma: 4, 13, 26, 40
Ortalama (1 + 2·2 + 4·3)/7 = 17/7 = 2,43. Ağacın derinliği ⌊log₂ 7⌋ + 1 = 3: en kötü durum. Ağaç bellekte kurulmaz; orta hesabı onu örtük olarak gezer.
Çoktan Seçmeli · İkili Arama
Soru 7: İlk Konumu Bulmak
Tekrarlı öğeler içeren sıralı dizide aranan değerin ilk konumunu bulmak için eşitlik durumunda (dizi[orta] == aranan) ne yapılmalıdır?
D: Eşleşme kaydedilir ve daha soldaki bir eşleşme için sol yarıda aranır; döngü bitince sonuc döner. Süre O(log n) kalır. C de doğru sonucu verir ama tüm öğeler eşitse O(n)'e çıkar; A herhangi bir eşleşmeyi verir, B son konuma gider.
Çıktı Sorusu · Hash ile Arama
Soru 8: Karakter Toplamı Hash'i
Sunumdaki hashFonksiyonu m = 10 ile "kar", "ark" ve "kara" anahtarları için hangi kovaları verir? (Unicode: a = 97, k = 107, r = 114)
int hashFonksiyonu(String anahtar, int m) { int toplam = 0; for (char k : anahtar.toCharArray()) toplam += k; return toplam % m; }
Cevabı göster
- "kar": 107 + 97 + 114 = 318 → 8
- "ark": 97 + 114 + 107 = 318 → 8 (çakışma)
- "kara": 318 + 97 = 415 → 5
Toplam harflerin sırasını görmez: aynı harflerden oluşan kelimeler her zaman çakışır. Java'nın String.hashCode()'u konuma bağlı ağırlık (Σ s[i] · 31ⁿ⁻¹⁻ⁱ) kullanarak bu sorunu azaltır.
Adım Adım Çalıştırma · Hash ile Arama
Soru 9: Doğrusal Yoklama ile Ekleme
Boş tabloya (m = 10) 23, 43, 13, 27, 37 sırayla hashEkle ile ekleniyor. Her anahtar hangi kovaya yerleşir? Ardından 33 aranırsa kaç kova yoklanır?
Boş tablo, m = 10, h(x) = x % 10. Sırayla 23, 43, 13, 27, 37 eklenecek; dolu kovada bir sonrakine geçilir (doğrusal yoklama).
h(23) = 3: kova boş → 23 buraya yerleşir.
h(43) = 3 dolu → 4 yoklanır; ilk boş kova 4. (2 yoklama)
h(13) = 3 dolu → 4, 5 yoklanır; ilk boş kova 5. (3 yoklama)
h(27) = 7: kova boş → 27 buraya yerleşir.
h(37) = 7 dolu → 8 yoklanır; ilk boş kova 8. (2 yoklama)
hashArama(33): h = 3 → 23, 43, 13 ile karşılaştırılır, kova 6 boş → −1. 4 kova yoklandı: 3, 4, 5 kovaları bitişik bir küme (birincil kümelenme) oluşturdu.
void hashEkle(Integer[] tablo, int anahtar) { int m = tablo.length; int indis = anahtar % m; while (tablo[indis] != null) indis = (indis + 1) % m; // sonraki tablo[indis] = anahtar; }
Çoktan Seçmeli · Hash ile Arama
Soru 10: Dolu Tablo
Doğrusal yoklama kullanan hashArama metoduyla, tamamen dolu bir tabloda tabloda olmayan bir anahtar aranırsa ne olur?
B: Döngü yalnızca boş (null) kovada durur; % m ile sondan başa dönüldüğü için dizi dışına da çıkılmaz ve tabloda sonsuza dek gezinilir. Çözüm: yük faktörünü sınırlamak (ör. α ≤ 0,75'te tabloyu büyütmek) ya da m yoklamadan sonra durmak.
Adım Adım Çalıştırma · Ara Değer Arama
Soru 11: Çarpık Dağılımda Ara Değer
araDegerArama(dizi, 8, 32) [2, 4, 8, 16, 32, 64, 128, 256] dizisinde çalışıyor. Her turda hangi indis tahmin edilir, kaç yoklama yapılır?
Dizi sıralı ama üstel artıyor (2, 4, 8, …, 256): düzgün dağılım varsayımı bozuk. Aranan 32.
indis = 0 + 210 / 254 = 0 (aşağı yuvarlanır); dizi[0] = 2 < 32 → bas = 1. 256 tahmini sola çeker.
indis = 1 + 168 / 252 = 1 (aşağı yuvarlanır); dizi[1] = 4 < 32 → bas = 2.
indis = 2 + 120 / 248 = 2 (aşağı yuvarlanır); dizi[2] = 8 < 32 → bas = 3.
indis = 3 + 64 / 240 = 3 (aşağı yuvarlanır); dizi[3] = 16 < 32 → bas = 4.
indis = 4 + 0 / 224 = 4; dizi[4] = 32 → return 4. 5 yoklama: ikili arama 3 yoklamada (3, 5, 4) bulurdu.
int araDegerArama(int[] dizi, int n, int aranan) { int bas = 0, son = n - 1; while (bas <= son && aranan >= dizi[bas] && aranan <= dizi[son]) { if (dizi[son] == dizi[bas]) return bas; int pay = (aranan - dizi[bas]) * (son - bas); int indis = bas + pay / (dizi[son] - dizi[bas]); if (dizi[indis] == aranan) return indis; if (dizi[indis] < aranan) bas = indis + 1; else son = indis - 1; } return -1; }
Çoktan Seçmeli · Ara Değer Arama
Soru 12: Ara Çarpımda Taşma
Ara değer aramada (aranan - dizi[bas]) * (son - bas) çarpımı için hangisi doğrudur?
D: Örneğin değerler 10⁹ mertebesinde ve son − bas 10⁶ ise çarpım int sınırını (2³¹ − 1) çok aşar. long ile hesaplanmalıdır. Önce bölmek (C) tam sayı bölmesinde sonucu değiştirir: çoğu zaman 0 çıkar.
Adım Adım Çalıştırma · Atlayarak Arama
Soru 13: Atlayarak Arama: Başarısız
atlayarakAraBul(dizi, 30, 16), D = [3, 8, 15, 21, 27, 34, 40, 46, 52, 59, 65, 71, 78, 84, 90, 97] için çalışıyor. Hangi indisler yoklanır, ne döner?
n = 16 → blok = √16 = 4. Aranan 30; her bloğun son öğesine bakılacak.
dizi[min(4, 16) − 1] = dizi[3] = 21 < 30 → bloğu atla.
konum = 4, atlama = 8. dizi[7] = 46 ≥ 30 → atlama biter; aranan [4, 8) bloğunda olabilir.
Doğrusal tarama: dizi[4] = 27 < 30 → konum = 5.
konum = 5 ≠ min(8, 16); dizi[5] = 34 < 30 yanlış → döngüden çıkılır.
dizi[5] = 34 ≠ 30 → −1. Yoklanan indisler 3, 7, 4, 5: 30, 27 ile 34 arasında olurdu. En kötü durum ≈ n/m + m − 1 = 7 yoklama.
int atlayarakAraBul(int[] dizi, int eleman, int n) { int blok = (int) Math.sqrt(n); int atlama = blok, konum = 0; while (dizi[Math.min(atlama, n) - 1] < eleman) { konum = atlama; atlama += blok; if (konum >= n) return -1; } while (dizi[konum] < eleman) { konum++; if (konum == Math.min(atlama, n)) return -1; } if (dizi[konum] == eleman) return konum; return -1; }
Çoktan Seçmeli · Atlayarak Arama
Soru 14: En İyi Blok Boyu
Atlayarak aramada blok boyu m iken en kötü yoklama ≈ n/m + (m − 1)'dir. n = 10.000 için en iyi m ve en kötü yoklama sayısı nedir?
A: f(m) = n/m + m − 1, f′(m) = −n/m² + 1 = 0 ⇒ m = √n = 100; 10.000/100 + 99 = 199 → O(√n). m = 50 için 200 + 49 = 249 yoklama; 14, ikili aramanın yoklama sayısıdır (⌊log₂ 10.000⌋ + 1).
Çıktı Sorusu · Üstel Arama
Soru 15: Üstel Aramada Yoklamalar
ustelArama(D, 27, 16) çağrısında (D = [3, 8, 15, 21, 27, 34, 40, 46, 52, 59, 65, 71, 78, 84, 90, 97]) hangi indisler yoklanır ve ne döner? İkili arama hangi aralıkta yapılır?
int ustelArama(int[] dizi, int aranan, int n) { if (dizi[0] == aranan) return 0; int konum = 1; while (konum < n && dizi[konum] <= aranan) konum *= 2; int bas = konum / 2; int son = Math.min(konum, n - 1); while (bas <= son) { int orta = (bas + son) / 2; if (dizi[orta] == aranan) return orta; if (dizi[orta] < aranan) bas = orta + 1; else son = orta - 1; } return -1; }
Cevabı göster
- dizi[0] = 3 ≠ 27
- Katlama: dizi[1] = 8, dizi[2] = 15, dizi[4] = 27 ≤ 27 → konum 1 → 2 → 4 → 8; dizi[8] = 52 > 27 → durur.
- Aralık [8/2, min(8, 15)] = [4, 8]; ikili arama: orta 6 (40 > 27) → son = 5; orta 4 → 27 bulundu.
Yoklanan indisler: 0, 1, 2, 4, 8, 6, 4 (7 yoklama); dönüş 4. İndis 4 iki kez yoklanır: katlama aşamasında ≤ testi, ikili aramada eşitlik testi. Maliyet O(log i), i = 4.
Çoktan Seçmeli · Üstel Arama
Soru 16: Üstel Arama Ne Zaman?
Üstel arama hangi durumda ikili aramadan daha uygundur?
C: Maliyet n'ye değil aranan öğenin indisine (i) bağlıdır: O(log i). Boyu bilinmeyen (sınırsız) listelerde ikili arama için önce bir üst sınır bulmak gerekir; katlama bunu yapar. A doğrusal aramanın, B ara değer aramanın, D atlayarak aramanın uygun olduğu durumlardır.
Çoktan Seçmeli · Karşılaştırma
Soru 17: Hangi Arama?
Sıralı kayıtlar bir manyetik bantta tutuluyor; ileri okumak ucuz, geri sarmak çok pahalı. Hangi arama yöntemi en uygundur?
B: Atlayarak arama √n'lik bloklar halinde hep ileri gider; yalnızca son bloğa bir kez geri döner ve onu sırayla okur: O(√n). İkili ve ara değer arama ileri-geri büyük sıçramalar yapar; hash tablosu ise kayıtların ayrıca bir tabloya yerleştirilmesini ister.
Klasik Soru · Karşılaştırma
Soru 18: Doğrusal mı, İkili mi?
Doğrusal ve ikili aramayı avantaj ve dezavantajlarıyla karşılaştırın. Sırasız n öğeli bir dizide k sorgu yapılacaksa hangisini, hangi koşulda seçersiniz?
Cevabı göster
- Doğrusal: önkoşul yok, basit, bağlı listede de çalışır; en kötü ve ortalama O(n).
- İkili: O(log n), büyük veride çok hızlı; ama sıralı dizi ve indisle O(1) erişim ister.
k sorgu: doğrusal toplam O(k · n); bir kez sırala + ikili O(n log n + k log n). k küçükse (ör. tek sorgu) doğrusal; k, log n mertebesini aşınca sıralamanın maliyeti kendini çıkarır. Örnek: n = 10⁶, k = 1000: doğrusal ≈ 10⁹, sırala + ikili ≈ 2 · 10⁷ + 2 · 10⁴ karşılaştırma.
Yalnızca tam eşleşme gerekiyorsa hash tablosu ortalama O(1) ile üçüncü seçenektir.