Bilgisayar bilimlerinin en temel problemlerinden biri, karmaşık bir veri yığınını belirli bir düzene sokmaktır. Peki, bir listeyi sıralamanın tek bir yolu mu var? Elbette hayır. Bazı yöntemler basit ama yavaşken, bazıları karmaşık ama inanılmaz hızlıdır. Bugün, Python kullanarak iki klasik yaklaşımı; Bubble Sort ve Merge Sort algoritmalarını derinlemesine inceleyeceğiz.
Verileri Düzenlemek: Bu Proje Ne Yapıyor?
Bu proje, Python’un kendi içindeki optimize edilmiş sıralama motoru olan Timsort (yani .sort() metodu) yerine, sıralama mantığını sıfırdan inşa etmeyi amaçlıyor. Amacımız, sadece kodu çalıştırmak değil, aynı zamanda algoritmik karmaşıklık (time complexity) kavramını somutlaştırmaktır.
Proje kapsamında iki farklı strateji uygulanıyor:
- Bubble Sort (Kabarcık Sıralaması): Yan yana olan elemanları karşılaştırıp yer değiştiren, öğrenmesi en kolay ama büyük veri setlerinde oldukça yavaş olan iteratif bir yöntem.
- Merge Sort (Birleştirmeli Sıralama): “Parçala ve Yönet” (Divide and Conquer) prensibini kullanan, veriyi küçük parçalara ayırıp sonra bunları düzenli bir şekilde birleştiren özyinelemeli (recursive) bir yaklaşım.
Bu iki algoritmayı aynı veri seti üzerinde çalıştırarak, kuadratik zaman karmaşıklığı ($O(n^2)$) ile lineeritmik zaman karmaşıklığı ($O(n \log n)$) arasındaki devasa farkı gözlemliyoruz.
Kodun Anatomisi
Kodun merkezinde, her iki algoritmanın da saf Python ile implemente edildiği iki ana fonksiyon yer alıyor.
1. Bubble Sort: Basit ve İteratif
Bubble Sort, listenin üzerinden defalarca geçer ve her adımda en büyük elemanı listenin sonuna “ittirir”. Kodda dikkat çeken en önemli nokta, swapped adındaki optimizasyon bayrağıdır. Eğer bir tur boyunca hiçbir eleman yer değiştirmediyse, liste zaten sıralanmış demektir ve döngüden erken çıkılarak zaman kazanılır.
2. Merge Sort: Akıllı ve Özyinelemeli
Merge Sort çok daha stratejik davranır. Önce listeyi tek bir eleman kalana kadar ikiye böler (Divide). Ardından, bu küçük parçaları sıralı bir şekilde birleştirerek yukarıya doğru yeniden inşa eder (Conquer). Bu işlem için _merge adında yardımcı bir alt rutin kullanılır.
# Merge Sort'un kalbi olan birleştirme (merge) mantığı
def _merge(left: list[int], right: list[int]) -> list[int]:
sorted_result = []
i = j = 0
# İki alt listeyi karşılaştırarak küçük olanı ekle
while i < len(left) and j < len(right):
if left[i] < right[j]:
sorted_result.append(left[i])
i += 1
else:
sorted_result.append(right[j])
j += 1
# Kalan elemanları ekle
sorted_result.extend(left[i:])
sorted_result.extend(right[j:])
return sorted_result
# Örnek Çıktı:
# Orijinal: [64, 34, 25, 12]
# Merge Sorted: [12, 25, 34, 64]
Nasıl Çalıştırılır?
Bu proje herhangi bir harici kütüphane gerektirmez; sadece standart Python kütüphanesi ile çalışır.
- Proje klasörüne gidin:
cd 31_custom_sorting_algorithms - Programı çalıştırın:
python main.py
Çalıştırdığınızda, konsol üzerinde her iki algoritmanın nasıl sonuç verdiği ve orijinal listenin (mutation engelleme sayesinde) nasıl korunduğu gösterilecektir.
Ne Öğrendik?
Bu projeyle birlikte şu kritik kavramları pekiştirdik:
- Zaman Karmaşıklığı: Bubble Sort’un $O(n^2)$ olan hızı, veri miktarı arttıkça hızla düşerken; Merge Sort’un $O(n \log n)$ performansı stabil kalır.
- Özyineleme (Recursion): Bir fonksiyonun kendi kendini çağırmasıyla büyük problemlerin nasıl küçük alt problemlere indirgenebileceğini gördük.
- Bellek Yönetimi: Merge Sort’un ek bellek alanına ($O(n)$ space complexity) ihtiyaç duyduğunu, Bubble Sort’un ise mevcut dizi üzerinde işlem yaptığını (in-place) fark ettik.
- Veri Güvenliği:
list(arr)yöntemiyle orijinal veriyi kopyalayarak, fonksiyonun dış dünyadaki veriyi istem dışı değiştirmesini engelledik.
Kaynaklar ve Sonraki Adımlar
Sıralama algoritmaları, bilgisayar bilimlerinin temelidir. Bir sonraki adım olarak Quick Sort veya Heap Sort gibi daha gelişmiş yöntemleri inceleyebilir, kendi implementasyonlarınızı oluşturabilirsiniz.
Ahmet Aksoy
Not: Bu yazıda incelediğimiz kodu ve benzer projelerin kaynak kodlarını https://github.com/ahmetax/practical-python-examples adresinde bulabilirsiniz.