Bölüm 3: Arama Algoritmaları

Bölüm 3: Arama Algoritmaları · Çalışma Soruları
Doğrusal ve bekçili aramaİkili aramaHash ile aramaAra değer aramaAtlayarak aramaÜstel aramaKarşılaştırma
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Çı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 < n yanlış olur ve kısa devre && sayesinde dizi[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?

125920701234bekçi

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.

125920701234i

dizi[0] = 12 ≠ 7 → i = 1. Döngüde yalnızca bir karşılaştırma var; i < n testi yok.

125920701234i

dizi[1] = 5 ≠ 7 → i = 2.

125920701234i

dizi[2] = 9 ≠ 7 → i = 3.

125920701234i

dizi[3] = 20 ≠ 7 → i = 4.

125920701234i

dizi[4] = 7 (bekçi) → döngü durur. Son hücreye sonEleman geri yazılır.

125920701234i

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.

baslangicbitisortadizi[orta]
0948
59721
89822
99931

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:

209314132640
  • 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?

0123456789

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).

230123456789

h(23) = 3: kova boş → 23 buraya yerleşir.

23430123456789

h(43) = 3 dolu → 4 yoklanır; ilk boş kova 4. (2 yoklama)

2343130123456789

h(13) = 3 dolu → 4, 5 yoklanır; ilk boş kova 5. (3 yoklama)

234313270123456789

h(27) = 7: kova boş → 27 buraya yerleşir.

23431327370123456789

h(37) = 7 dolu → 8 yoklanır; ilk boş kova 8. (2 yoklama)

23431327370123456789

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?

24816326412825601234567

Dizi sıralı ama üstel artıyor (2, 4, 8, …, 256): düzgün dağılım varsayımı bozuk. Aranan 32.

24816326412825601234567indis

indis = 0 + 210 / 254 = 0 (aşağı yuvarlanır); dizi[0] = 2 < 32 → bas = 1. 256 tahmini sola çeker.

24816326412825601234567indis

indis = 1 + 168 / 252 = 1 (aşağı yuvarlanır); dizi[1] = 4 < 32 → bas = 2.

24816326412825601234567indis

indis = 2 + 120 / 248 = 2 (aşağı yuvarlanır); dizi[2] = 8 < 32 → bas = 3.

24816326412825601234567indis

indis = 3 + 64 / 240 = 3 (aşağı yuvarlanır); dizi[3] = 16 < 32 → bas = 4.

24816326412825601234567indis

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?

3815212734404652596571788490970123456789101112131415

n = 16 → blok = √16 = 4. Aranan 30; her bloğun son öğesine bakılacak.

3815212734404652596571788490970123456789101112131415yokla

dizi[min(4, 16) − 1] = dizi[3] = 21 < 30 → bloğu atla.

3815212734404652596571788490970123456789101112131415yokla

konum = 4, atlama = 8. dizi[7] = 46 ≥ 30 → atlama biter; aranan [4, 8) bloğunda olabilir.

3815212734404652596571788490970123456789101112131415yokla

Doğrusal tarama: dizi[4] = 27 < 30 → konum = 5.

3815212734404652596571788490970123456789101112131415yokla

konum = 5 ≠ min(8, 16); dizi[5] = 34 < 30 yanlış → döngüden çıkılır.

3815212734404652596571788490970123456789101112131415

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.

Son

Bölüm 3: Arama Algoritmaları: Çalışma Soruları
Konu anlatımı: Bölüm 3: Arama Algoritmaları · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.