Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Binary Search Derinlemesine: Lower Bound, Off-by-One ve Cevap Üzerinde Binary Search
Binary search'ü doğru yazmanın yolu bir invariant'a, ör. half-open [lo, hi) aralığına göre yazmak; 1 milyon elemanda en fazla 20 karşılaştırma yapar ama lo = mid gibi tek bir sınır hatası onu sonsuz döngüye sokar. Yazıda lower ve upper bound'u, Array.BinarySearch'ün ~index dönüşünü, minimum kamyon kapasitesini bulan cevap üzerinde binary search'ü ve log'da zaman aralığı aramayı xUnit testleriyle yazıyoruz.
Quick Sort, Introsort ve Counting/Radix Sort: .NET'in Array.Sort'u Nasıl Sıralar
Array.Sort introsort kullanır: quick sort, derinlik 2·log n'i aşınca heapsort, 16 ve altı element'te insertion sort; bu yüzden son element'i pivot seçen ders kitabı quick sort'u sıralı 10.000 elemanda 749 kat yavaşlarken Array.Sort etkilenmez. Yazıda Lomuto ve Hoare partition'ı, median-of-three'yi, Ω(n log n) alt sınırını, Array.Sort'tan 11–12 kat hızlı counting ve radix sort'u ve a - b comparer tuzağını testlerle anlatıyoruz.
Sorting Algoritmaları 1: Insertion Sort, Merge Sort ve Stability
Array.Sort stable değil: tarihe göre sıralı 200 siparişi müşteriye göre sıralayınca her müşterinin tarih sırası bozuluyor, merge sort ve LINQ OrderBy ise koruyor. Yazıda insertion sort'u (neredeyse sıralı 10.000 elemanda Array.Sort'tan 6 kat hızlı), top-down ve bottom-up merge sort'u, external merge sort fikrini ve stability'yi xUnit testleri ve BenchmarkDotNet ölçümleriyle anlatıyoruz.
Array ve Hashing Pattern'leri: Two Pointers, Sliding Window, Prefix Sum ve Frequency Map
İç içe döngünün tekrar tekrar hesapladığını bir kez hesaplayıp saklamak, two sum'ı O(n²)'den O(n)'e indiriyor: 100.000 fiyatta brute force 1,69 saniye, Dictionary'li versiyon 0,32 ms sürüyor. Yazıda frequency map ve CountBy'ı, two pointers'ı, sabit ve değişken genişlikli sliding window'u, TimeProvider ile test edilen bir rate limiter'ı ve prefix sum + Dictionary ile toplamı k olan aralıkları saymayı xUnit testleriyle anlatıyoruz.
Hash Table Nasıl Çalışır: C# ile Kendi HashMap'ini Yazmak, Collision ve Load Factor
Hash table, key'in hash code'undan bucket index'i hesaplayıp collision'ları chaining ya da open addressing ile çözer; her zaman 42 dönen bir GetHashCode, 10.000 key'lik Dictionary'yi 967 kat yavaşlatıyor. Yazıda .NET Dictionary ile aynı iç yapıda (buckets + entries, free list, prime boyutlar) kendi HashMap'imizi, tombstone'lu linear probing'i, randomized string hashing'i ve bir Bloom filter'ı xUnit testleriyle yazıyoruz.
C#'ta Recursion: Base Case, Call Stack, StackOverflowException ve Iterative'e Çevirmek
StackOverflowException .NET'te yakalanamaz ve bütün process'i öldürür; 8 MB'lık ana thread'de boş bir method yaklaşık 130.650 kez kendini çağırabildi, catch bloğu hiç çalışmadı. Yazıda recursion'ın anatomisini, call stack frame'lerini, recursive kodu explicit Stack<T> ile iterative'e çevirmeyi, JSON MaxDepth (64) ve EnsureSufficientExecutionStack gibi derinlik savunmalarını xUnit testleri ve gerçek çıktılarla anlatıyoruz.
C# ile Stack, Queue ve Ring Buffer: Kendi Implementasyonun ve Gerçek Kullanımlar
Queue'yu array üzerinde O(1) yapan şey circular buffer: element'leri kaydırmak yerine head ve tail index'leri sarılarak ilerliyor; List.RemoveAt(0) ile kurulan kuyruk 100.000 siparişte Queue<T>'den 497 kat yavaş. Yazıda array tabanlı stack, büyürken halkayı açan circular queue, overflow politikalı bounded ring buffer, parantez doğrulama, undo/redo ve monotonic stack'i xUnit testleriyle yazıyoruz.
C# ile Linked List: Node'lar, Sentinel ve Klasik Linked List Problemleri
Linked list, elinde tuttuğun node'u O(1)'de çıkarır ama her element için ayrı bir object öder: 100.000 int List'te 400 KB, LinkedList<int>'te 4,8 MB tutuyor ve node'lar bellekte dağınıkken 1 milyon elemanı gezmek List'ten 259 kat yavaş. Yazıda sentinel'li singly ve doubly linked list, in-place reverse, Floyd cycle detection, ortadaki node ve sıralı merge'ü xUnit testleriyle yazıyoruz.
C# ile Array ve Dynamic Array: Contiguous Bellek, Index Erişimi ve Kendi List'ini Yazmak
Dynamic array, dolunca iki katı büyüklükte yeni bir array'e taşınan bir array'dir; 1.000.000 Add toplamda yalnız 1.048.572 kopyalama yapar, yani element başına maliyet sabittir. Yazıda kendi DynamicArray<T>'imizi xUnit testleriyle yazıyor, silinen slot'u GC için temizlemenin nedenini ve 4.000×4.000'lik grid'i sütun sütun gezmenin satır satır gezmekten 3 kat yavaş olduğunu BenchmarkDotNet ile gösteriyoruz.
Algoritmalar ve Data Structure'lar Neden Hâlâ Önemli: .NET Geliştiricisi İçin Yol Haritası
Doğru data structure, aynı kodu veri büyüdüğünde ayakta tutar: 100.000 kitaplık katalogda 100 ISBN araması List ile 9,7 ms, sıralı array'de binary search ile 6,5 µs, Dictionary ile 0,93 µs sürüyor. Yazı abstract data type ile implementation farkını, serinin xUnit ve BenchmarkDotNet'li çalışma düzenini ve 22 yazılık yol haritasını anlatıyor.