Yazılım geliştirmenin temelini oluşturan iki kavram var: veri yapıları ve algoritmalar. Bunlar olmadan etkili ve ölçeklenebilir yazılımlar geliştirmek neredeyse imkansız. Büyük teknoloji şirketlerinin mülakat süreçlerinde bu konulara bu kadar ağırlık vermesinin bir sebebi var: Verileri doğru yapıda depolamak ve doğru algoritmayla işlemek, yazılımın performansını belirleyen en kritik faktörler.
Algoritma Nedir?
Algoritma, belirli bir problemi çözmek için tasarlanmış adım adım yönergeler topluluğudur. Bir yemek tarifine benzetebilirsiniz: malzemeleri sırayla nasıl birleştireceğinizi, hangi sıcaklıkta ne kadar pişireceğinizi anlatan talimatlar.
Her algoritmanın bir başlangıcı ve sonu vardır. Her adımda yapılacak işlem açıkça belirtilir. Belirsizlik yoktur; aynı girdi her zaman aynı çıktıyı üretir.
Veri Yapısı Nedir?
Veri yapısı, verilerin bellekte nasıl organize edildiğini tanımlar. Doğru veri yapısı seçimi, verilere hızlı erişim ve verimli işleme sağlar. Yanlış seçim ise performans sorunlarına yol açar.
Verimli algoritmalar oluşturmanın anahtarı veri yapılarını anlamaktan geçer. Hangi durumda hangi yapıyı kullanacağınızı bilmek, yazılım geliştirmede kritik bir beceridir.
Temel Veri Yapıları
Dizi (Array)
Dizi, verilerin ardışık bellek konumlarında sıralı şekilde depolandığı yapıdır. Bir kitaplığın rafındaki yan yana duran kitaplar gibi düşünebilirsiniz. Her elemanın bir indeksi vardır ve bu indeksle doğrudan erişim sağlanır.
Artıları: İndeks ile O(1) sabit zamanlı erişim. Basit ve anlaşılır yapı. Bellek açısından verimli.
Eksileri: Boyut sabittir, büyütmek maliyetlidir. Ortadan eleman ekleme veya silme O(n) zaman alır. Ardışık bellek gerektirir.
Kullanım alanları: Sıralı veri listesi, matris işlemleri, önbellek dostu uygulamalar.
Bağlı Liste (Linked List)
Bağlı liste, elemanların düğümler halinde birbirine bağlandığı yapıdır. Her düğüm iki bilgi içerir: veri ve sonraki düğümün adresi. Elemanların bellekte yan yana olması gerekmez.
Artıları: Dinamik boyut, bellek ayırma esnekliği. Başa veya sona ekleme O(1). Ortadan silme O(1) (düğüme ulaşıldıysa).
Eksileri: İndeksle erişim yok, n. elemana ulaşmak O(n). Her düğüm ekstra bellek kullanır (pointer için). Cache dostu değil, çünkü elemanlar bellekte dağınık.
Türleri: Tek yönlü (singly linked), çift yönlü (doubly linked), dairesel (circular) bağlı listeler.
Yığın (Stack)
Yığın, LIFO (Last-In, First-Out) prensibine göre çalışır. Son giren eleman ilk çıkar. Üst üste dizilmiş tabakları düşünün: yeni tabağı en üste koyarsınız ve almanız gerektiğinde en üsttekini alırsınız.
Temel işlemler: push (üste ekle), pop (üstten çıkar), peek (üsttekine bak).
Kullanım alanları: Fonksiyon çağrı yığını (call stack), geri alma işlemleri (undo), parantez eşleştirme, tarayıcı geçmişi.
Kuyruk (Queue)
Kuyruk, FIFO (First-In, First-Out) prensibine göre çalışır. İlk giren eleman ilk çıkar. Otobüs durağındaki bekleme sırası gibi: sırada ilk bekleyen kişi ilk biner.
Temel işlemler: enqueue (sona ekle), dequeue (baştan çıkar), peek (baştakine bak).
Kullanım alanları: Yazıcı kuyrukları, mesaj kuyrukları, BFS (genişlik öncelikli arama), işlem zamanlama.
Öncelikli kuyruk (priority queue) versiyonunda elemanlar önceliğe göre sıralanır, ilk giren değil en yüksek öncelikli eleman ilk çıkar.
Hash Table (Hash Map)
Hash table, anahtar-değer çiftlerini depolayan yapıdır. Hash fonksiyonu, anahtarı bir indekse dönüştürür ve değer bu indekse yerleştirilir.
Artıları: Ortalama O(1) ekleme, silme ve arama. Anahtarla doğrudan erişim.
Eksileri: En kötü durumda O(n) (çarpışma yoğunsa). Sırasız, elemanların sırası garanti değil. Hash fonksiyonu kalitesi kritik.
Kullanım alanları: Veritabanı indeksleme, önbellek, sembol tabloları, sözlük uygulamaları.
Ağaç (Tree)
Ağaç, hiyerarşik yapıya sahip veri yapısıdır. Bir kök düğüm ve ona bağlı alt düğümlerden oluşur. Dosya sistemi yapısını düşünün: klasörler içinde klasörler, onların içinde dosyalar.
İkili Arama Ağacı (BST): Sol alt ağaç köke göre küçük, sağ alt ağaç büyük değerler içerir. Dengeli BST'de arama O(log n).
Dengeli Ağaçlar: AVL ve Red-Black ağaçları otomatik dengeleme sağlar. Dengesiz ağaçlar en kötü durumda listeye dönüşür.
Kullanım alanları: Dosya sistemleri, veritabanı indeksleri, karar ağaçları, sıkıştırma algoritmaları.
Graf (Graph)
Graf, düğümlerin kenarlarla bağlandığı yapıdır. Sosyal ağlar, yol haritaları, bilgisayar ağları graf yapısında modellenir.
Türleri: Yönlü (directed) ve yönsüz (undirected), ağırlıklı ve ağırlıksız.
Gösterim: Komşuluk matrisi (adjacency matrix) veya komşuluk listesi (adjacency list).
Kullanım alanları: Sosyal ağ analizi, navigasyon sistemleri, öneri sistemleri, bağımlılık çözümleme.
Big O Notasyonu: Karmaşıklık Analizi
Big O notasyonu, algoritmanın girdi boyutu büyüdükçe nasıl performans gösterdiğini ifade eder. Bu, kodunuzun ölçeklenebilirliğini anlamamın anahtarıdır.
Yaygın Karmaşıklık Sınıfları
O(1) - Sabit Zaman: Girdi boyutundan bağımsız, işlem süresi değişmez. Dizide indeksle erişim, hash table'da anahtar ile arama örnek verilebilir.
O(log n) - Logaritmik: Girdi ikiye katlandığında, işlem sadece bir adım artar. İkili arama (binary search) bu kategoride.
O(n) - Doğrusal: İşlem süresi girdi boyutuyla doğru orantılı artar. Sırasız dizide eleman arama örneği.
O(n log n) - Doğrusal-logaritmik: Karşılaştırma tabanlı sıralama algoritmalarının optimal alt sınırı. Merge sort ve quick sort ortalama durumda bu kategoride.
O(n²) - Karesel: Girdi iki katına çıktığında, işlem süresi dört katına çıkar. İç içe döngüler genellikle bu kategoride. Bubble sort, selection sort örnekleri.
O(2^n) - Üstel: Her ek girdi elemanı için işlem süresi iki katına çıkar. Brute force yaklaşımlar genellikle bu kategoride. Fibonacci'nin naif recursive çözümü örnek verilebilir.
O(n!) - Faktöriyel: En yavaş kategori. Gezgin satıcı probleminin brute force çözümü örneği.
Zaman ve Alan Karmaşıklığı
Mülakatlarda hem zaman hem alan karmaşıklığı sorulur. Bazı algoritmalar hız için bellekten fedakarlık yapar veya tam tersi. Bu trade-off'ları anlamak önemlidir.
Temel Sıralama Algoritmaları
Bubble Sort
En basit sıralama algoritması. Bitişik elemanları karşılaştırır, yanlış sıradaysa değiştirir. Bu işlem liste sıralanana kadar tekrarlanır.
Karmaşıklık: En kötü ve ortalama O(n²), en iyi O(n) (zaten sıralıysa). Kararlı (stable) bir algoritmadır.
Pratikte neredeyse hiç kullanılmaz ama öğretim amacıyla değerlidir. Büyük veri setlerinde pratik değildir.
Selection Sort
Sırasız bölümden en küçük elemanı bulur, sıralı bölümün sonuna ekler. Bu işlem tüm elemanlar için tekrarlanır.
Karmaşıklık: Her durumda O(n²). Kararsız (unstable).
Bellek kullanımı düşük ama büyük veriler için yavaş.
Insertion Sort
Sıralı bir alt dizi korur ve her yeni elemanı doğru konuma yerleştirir. Kart oyununda el düzenlemeye benzer.
Karmaşıklık: En kötü O(n²), en iyi O(n) (zaten sıralıysa).
Küçük veri setleri ve neredeyse sıralı veriler için verimli. Hibrit algoritmalarda (Timsort) temel durum olarak kullanılır.
Merge Sort
Böl ve fethet (divide and conquer) stratejisi kullanır. Diziyi ikiye böler, her yarıyı ayrı sıralar, sonra birleştirir.
Karmaşıklık: Her durumda O(n log n). Kararlı.
Ekstra O(n) bellek gerektirir ama kararlılık gerektiğinde tercih edilir. Paralel hesaplama ortamlarında iyi performans gösterir.
Quick Sort
Bir pivot eleman seçer, küçükleri sola, büyükleri sağa taşır. Alt dizileri recursive olarak sıralar.
Karmaşıklık: Ortalama O(n log n), en kötü O(n²) (kötü pivot seçimi).
Yerinde (in-place) çalışır, ekstra bellek gerekmez. Cache dostu olması nedeniyle pratikte çok hızlı.
2025 çalışmalarına göre optimized Quick Sort, çoğu durumda en hızlı performansı gösteriyor. Pivot seçimi iyileştirildiğinde en kötü durum riski minimize edilir.
Heap Sort
Yığın veri yapısını kullanır. Max-heap oluşturur, kökü (en büyüğü) alıp sona koyar, tekrarlar.
Karmaşıklık: Her durumda O(n log n). Kararsız.
Yerinde çalışır ama cache dostu değil.
Modern Hibrit Yaklaşımlar
Gerçek dünya uygulamalarında saf algoritma yerine hibrit yaklaşımlar kullanılır:
Timsort (Python, Java, Android): Merge sort ve insertion sort kombinasyonu. Gerçek dünya verilerinde çok iyi performans.
Introsort (C++ STL): Quick sort ile başlar, derinlik eşiği aşılırsa heap sort'a geçer.
Temel Arama Algoritmaları
Doğrusal Arama (Linear Search)
Her elemanı sırayla kontrol eder. Sırasız veriler için tek seçenek.
Karmaşıklık: O(n).
İkili Arama (Binary Search)
Sıralı veri gerektirir. Ortadaki elemanı kontrol eder, aranan değere göre sol veya sağ yarıya geçer.
Karmaşıklık: O(log n).
1 milyon elemanlı sıralı dizide en fazla 20 karşılaştırma yeterli. Doğrusal aramada 1 milyon karşılaştırma gerekebilir.
Graf Algoritmaları
BFS (Breadth-First Search)
Genişlik öncelikli arama. Başlangıç düğümünden başlar, önce tüm komşuları ziyaret eder, sonra komşuların komşularını.
Kuyruk veri yapısı kullanır. En kısa yol problemlerinde (ağırlıksız graf) kullanılır.
DFS (Depth-First Search)
Derinlik öncelikli arama. Bir yolda sonuna kadar gider, sonra geri dönerek diğer yolları dener.
Yığın veri yapısı veya recursive çağrılar kullanır. Topolojik sıralama ve döngü tespitinde kullanılır.
Dijkstra Algoritması
Ağırlıklı graflarda en kısa yol bulur. Navigasyon sistemlerinin temelini oluşturur.
Karmaşıklık: Öncelikli kuyruk ile O((V+E) log V).
Mülakat Stratejileri
Teknik mülakatlarda veri yapıları ve algoritmalar merkezi rol oynar. Google, Amazon, Facebook ve Microsoft gibi şirketler bu konularda derinlemesine bilgi bekler.
Pratik yapılacak platformlar: LeetCode, HackerRank, CodeSignal, Project Euler.
Önerilen kitaplar: "Cracking the Coding Interview" en popüler kaynak. "Introduction to Algorithms" (CLRS) akademik referans. "Grokking Algorithms" görsel öğrenenler için ideal.
Öğrenme stratejisi: Önce temel veri yapılarını anlayın. Big O notasyonunu içselleştirin. Ardından temel algoritmalara geçin. Günlük pratikle pekiştirin.
Her veri yapısının güçlü ve zayıf yanlarını bilin. Doğru silahı doğru savaşa taşımak, zaferin anahtarıdır.
Sonuç
Veri yapıları ve algoritmalar, yazılım geliştirmenin temel taşları. Bunları öğrenmek zaman alır ama kariyeriniz boyunca faydasını göreceksiniz.
Küçük veri setlerinde performans farkı görünmeyebilir. Ancak kullanıcı sayısı arttığında, veri büyüdüğünde doğru veri yapısı ve algoritma seçimi kritik hale gelir.
Pratik yaparak öğrenin. Teorik bilgi önemli ama gerçek problemler üzerinde çalışmak bilgiyi kalıcı kılar. Her gün bir algoritma problemi çözmek, uzun vadede büyük fark yaratır.
0 Yorum
Yorum Yaz