12 - Arama Algoritmaları
2026
Bir dizide, listede veya veri kümesinde belirli bir değerin bulunup bulunmadığını öğrenmek sık karşılaşılan bir işlemdir.
Örneğin:
Arama algoritmaları, bu tür sorulara sistematik biçimde cevap vermek için kullanılır.
Elimizde şu dizi olsun:
2, 4, 0, 1, 9
Aranan değer: 1
Soru:
Doğrusal arama, veri yapısındaki elemanları baştan sona sırayla kontrol eder.
Aranan değer bulunursa ilgili indis döndürülür.
Aranan değer dizi içinde yoksa, tüm elemanlar kontrol edildikten sonra bulunamadı sonucu döndürülür.
Doğrusal arama özellikle şu durumlarda uygundur:
Doğrusal arama basittir; ancak büyük veri kümelerinde yavaş kalabilir.
Aşağıdaki dizide k = 1 değerini arayalım.
İlk elemandan başlanır.
Her eleman aranan değerle karşılaştırılır: array[i] == k
Eğer eşleşme varsa ilgili indis döndürülür.
Eşleşme bulunursa arama biter.
Eşleşme yoksa bir sonraki elemana geçilir.
Dizi sonuna kadar eşleşme bulunamazsa -1 döndürülür.
-1 döndürülür.#include <stdio.h>
int search(int array[], int n, int x) {
for (int i = 0; i < n; i++) {
if (array[i] == x) {
return i;
}
}
return -1;
}
int main(void) {
int array[] = {2, 4, 0, 1, 9};
int x = 1;
int n = sizeof(array) / sizeof(array[0]);
int result = search(array, n, x);
if (result == -1) {
printf("Eleman bulunamadı\n");
} else {
printf("Eleman %d indisinde bulundu\n", result);
}
return 0;
}Doğrusal aramada yapılacak karşılaştırma sayısı, aranan değerin dizideki konumuna bağlıdır.
| Durum | Açıklama | Karmaşıklık |
|---|---|---|
| En iyi durum | Aranan değer ilk elemandadır | O(1) |
| Ortalama durum | Aranan değer dizinin ortalarındadır | O(n) |
| En kötü durum | Aranan değer sonda ya da dizide yoktur | O(n) |
Dizi küçükse doğrusal arama yeterli olabilir.
Ancak dizi çok büyükse her elemanı sırayla kontrol etmek maliyetli hale gelir.
Örneğin 1.000.000 elemanlı bir dizide, aranan değer en sondaysa 1.000.000 karşılaştırma gerekebilir.
Bu durumda daha etkili bir yöntem düşünülebilir.
İkili arama, sıralanmış bir dizideki bir elemanın konumunu bulmak için kullanılan bir arama algoritmasıdır.
Temel fikir: Her adımda arama alanı ikiye bölünür.
Bu nedenle ikili arama, doğrusal aramaya göre büyük veri kümelerinde çok daha az karşılaştırma yapabilir.
İkili arama yalnızca sıralı dizilerde doğru çalışır.
Örnek sıralı dizi:
3, 4, 5, 6, 7, 8, 9
Bu dizide küçük değerler solda, büyük değerler sağdadır.
Bu düzen sayesinde arama alanının hangi yarısının eleneceğine karar verilebilir.
Sıralı olmayan bir dizi düşünelim:
8, 3, 10, 1, 6
Aranan değer: 1
Ortadaki değer 10 olsun.
1 < 10 olduğu için sol tarafa geçmek doğru gibi görünebilir.
Ancak dizi sıralı olmadığı için 1 değerinin solda olacağı garanti değildir.
İkili aramada üç temel indis kullanılır:
| Değişken | Anlamı |
|---|---|
low |
Arama aralığının başlangıç indisi |
high |
Arama aralığının bitiş indisi |
mid |
Arama aralığının orta indisi |
Dikkat edilmesi gereken ayrım:
mid: indisarray[mid]: o indisteki değerOrta indis şu şekilde hesaplanır:
mid = low + (high - low) / 2;
Bu yazım, şu ifadeye göre daha güvenlidir:
mid = (low + high) / 2;
Çünkü çok büyük dizilerde low + high toplamı tam sayı taşmasına neden olabilir.
Sıralı dizimiz:
3, 4, 5, 6, 7, 8, 9
Aranan değer: x = 4
Başlangıçta arama tüm dizi üzerinde yapılır.
low = 0high = n - 1Örnek durumda:
low = 0high = 6mid = 3array[mid] = 6Aranan değer 4, orta değer 6dan küçüktür.
Bu nedenle arama sağ tarafta değil, sol tarafta devam eder.
x < array[mid] olduğu için sağ taraf elenir.
Yeni arama aralığı: high = mid - 1;
mid tekrar aralığa dahil edilmez; çünkü array[mid] zaten kontrol edilmiştir.
Bu tercih gereksiz tekrarları ve olası sonsuz döngüleri önler.
Yeni aralıkta tekrar orta indis hesaplanır.
low <= high olduğu sürece arama devam eder.
Eğer array[mid] == x koşulu sağlanırsa aranan değer bulunmuştur.
Bu durumda mid indisi döndürülür.
low değerini dizinin ilk indisi olarak belirle.high değerini dizinin son indisi olarak belirle.low <= high olduğu sürece:
mid indisini hesapla.array[mid] == x ise mid değerini döndür.array[mid] < x ise sağ yarıda ara.array[mid] > x ise sol yarıda ara.-1 döndür.Aşağıdaki kod yalnızca binarySearch fonksiyonunu göstermektedir. Fonksiyonun nasıl çağrılacağı ilerleyen slaytta ortak main fonksiyonu ile gösterilecektir.
İkili arama özyinelemeli olarak da yazılabilir.
Bu yaklaşımda her çağrıda arama aralığı küçültülür.
Aşağıdaki kod yalnızca binarySearch fonksiyonunu göstermektedir. Tam program için bu fonksiyon, ilerleyen slaytta verilen ortak main fonksiyonu ve #include <stdio.h> satırıyla birlikte kullanılabilir.
Her iki yöntem de aynı temel fikre dayanır: arama aralığını her adımda küçültmek.
Ancak uygulama biçimleri farklıdır.
| Yaklaşım | Özellik |
|---|---|
| İteratif | Döngü kullanır |
| Özyinelemeli | Fonksiyon kendisini tekrar çağırır |
| İteratif | Genellikle daha az bellek kullanır |
| Özyinelemeli | Çağrı yığını nedeniyle ek bellek kullanabilir |
Aşağıdaki main fonksiyonu, verilen binarySearch fonksiyonuyla birlikte kullanılabilir.
İkili aramada her adımda arama aralığı yaklaşık olarak yarıya iner.
| Durum | Açıklama | Karmaşıklık |
|---|---|---|
| En iyi durum | Aranan değer ilk orta elemandadır | O(1) |
| Ortalama durum | Arama aralığı birkaç kez ikiye bölünür | O(log n) |
| En kötü durum | Değer en son adımda bulunur ya da yoktur | O(log n) |
1.000.000 elemanlı bir dizide:
| Algoritma | En kötü durumda yaklaşık karşılaştırma |
|---|---|
| Doğrusal arama | 1.000.000 |
| İkili arama | 20 |
İkili arama bu nedenle büyük ve sıralı veri kümelerinde daha avantajlıdır.
| Özellik | Doğrusal Arama | İkili Arama |
|---|---|---|
| Sıralama gerekli mi? | Hayır | Evet |
| Çalışma biçimi | Elemanları sırayla kontrol eder | Arama aralığını ikiye böler |
| En iyi durum | O(1) | O(1) |
| En kötü durum | O(n) | O(log n) |
| Küçük veri için uygun mu? | Evet | Evet, fakat sıralama gerekir |
| Büyük ve sıralı veri için uygun mu? | Daha yavaş kalabilir | Daha uygundur |
İkili arama hızlıdır; ancak yalnızca sıralı dizide çalışır.
Eğer veri sıralı değilse önce sıralama yapılmalıdır.
Bu nedenle şu soru önemlidir: Veri zaten sıralı mı?
Eğer veri yalnızca bir kez aranacaksa sıralama yapmak her zaman avantajlı olmayabilir.
Eğer aynı veri üzerinde çok sayıda arama yapılacaksa, veriyi sıralayıp ikili arama kullanmak daha anlamlı olabilir.
Dizide aranan değerden birden fazla olabilir.
Örnek dizi: 2, 4, 4, 4, 9
Bu durumda doğrusal arama ilk karşılaştığı eşleşmenin indisini döndürür.
İkili aramada ise bulunan eşleşmenin ilk, son veya ortadaki tekrar olacağı garanti değildir.
İlk ya da son eşleşme özellikle isteniyorsa algoritma buna göre değiştirilmelidir.
C standart kütüphanesinde ikili arama için bsearch() fonksiyonu bulunur.
Bu fonksiyon <stdlib.h> içinde tanımlıdır.
Ancak bsearch() kullanabilmek için:
Bu derste algoritmanın mantığını öğrenmek için kendi ikili arama fonksiyonumuzu yazıyoruz.
Her iki algoritmada da aranan değer bulunamayabilir.
Bu durumda genellikle -1 döndürülür.
Bu değer, geçerli bir dizi indisi değildir.
Bu nedenle “aranan eleman bulunamadı” anlamında kullanılabilir.
Arama algoritması seçimi, verinin yapısına bağlıdır.
| Veri / Problem Türü | Örnek Arama Yaklaşımları |
|---|---|
| Sıralı diziler | İkili arama, Jump Search, Interpolation Search |
| Anahtar-değer verileri | Hash tablosu ile arama |
| Ağaçlar | Binary Search Tree üzerinde arama |
| Graflar | Breadth-First Search, Depth-First Search |
| Metinler | KMP, Boyer-Moore |
Bu derste temel mantığı öğrenmek için doğrusal arama ve ikili arama yeterlidir.
mid ile array[mid] arasındaki fark nedir?Bu derste iki temel arama algoritmasını inceledik.
Doğrusal arama basit ve genel bir çözümdür.
İkili arama ise sıralı veri üzerinde daha etkili bir çözümdür.
Bir arama algoritması seçerken verinin sıralı olup olmadığı, veri kümesinin büyüklüğü ve kaç kez arama yapılacağı birlikte düşünülmelidir.