<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sonsuzus.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sonsuzus.github.io/" rel="alternate" type="text/html" /><updated>2026-08-05T07:13:26+00:00</updated><id>https://sonsuzus.github.io/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">Big O ile Doğru Algoritmayı Seçmek: Hız ve Bellek Dengesi</title><link href="https://sonsuzus.github.io/posts/big-o-ile-dogru-algoritmayi-secmek-hiz-ve-bellek-dengesi/" rel="alternate" type="text/html" title="Big O ile Doğru Algoritmayı Seçmek: Hız ve Bellek Dengesi" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/big-o-ile-dogru-algoritmayi-secmek-hiz-ve-bellek-dengesi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/big-o-ile-dogru-algoritmayi-secmek-hiz-ve-bellek-dengesi/"><![CDATA[<p>Bir problemi çözen ilk algoritmayı bulmak güzeldir; ancak milyonlarca veri geldiğinde hâlâ çalışan algoritmayı bulmak çok daha güzeldir. Big O notasyonu, farklı algoritmaların veri büyüdükçe nasıl davranacağını karşılaştırmamızı sağlar. Böylece yalnızca çalışan değil, zaman ve bellek açısından sürdürülebilir çözümler seçebiliriz.
``</p>

<h2 id="big-o-neyi-ölçer">Big O neyi ölçer?</h2>

<p>Big O, bir algoritmanın girdi boyutu $n$ büyürken kaynak tüketiminin hangi hızla arttığını ifade eder. Tam çalışma süresini saniye cinsinden söylemez; donanım, programlama dili ve derleyici gibi ayrıntıları göz ardı ederek büyüme eğilimini gösterir.</p>

<p>Örneğin bir döngü $n$ elemanın tamamını geziyorsa zaman karmaşıklığı $O(n)$ olur. İç içe iki döngünün her biri $n$ kez çalışıyorsa yaklaşık $n \times n=n^2$ işlem yapılır ve sonuç $O(n^2)$ olarak gösterilir.</p>

<p>Big O hesaplanırken sabit katsayılar ve düşük dereceli terimler atılır:</p>

\[T(n)=4n^2+7n+12 \Rightarrow O(n^2)\]

<p>Çünkü büyük $n$ değerlerinde davranışı belirleyen baskın terim $n^2$ olur.</p>

<p>| Karmaşıklık | Tipik örnek | Büyüme davranışı |
|—|—|—|
| $O(1)$ | Dizide indeksle erişim | Girdiden bağımsız |
| $O(\log n)$ grid | İkili arama | Çok yavaş büyür |
| $O(n)$ | Doğrusal arama | Girdiyle aynı oranda büyür |
| $O(n\log n)$ | Merge Sort | Büyük veriler için genellikle uygundur |
| $O(n^2)$ | İç içe döngüler | Büyük girdilerde pahalıdır |
l
| $O(2^n)$ ring | Alt kümeleri denemek | Küçük girdilerde bile patlayabilir |</p>

<h2 id="zaman-karmaşıklığı-nasıl-analiz-edilir">Zaman karmaşıklığı nasıl analiz edilir?</h2>

<p>Önce temel işlemin kaç kez çalıştığını belirlemek gerekir. Ardışık işlemlerin maliyetleri toplanır, iç içe işlemlerin maliyetleri ise çarpılır. Ardından baskın terim seçilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">tekrar_var_mi</span><span class="p">(</span><span class="n">liste</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">liste</span><span class="p">)):</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">liste</span><span class="p">)):</span>
            <span class="k">if</span> <span class="n">liste</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">liste</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
                <span class="k">return</span> <span class="bp">True</span>
    <span class="k">return</span> <span class="bp">False</span>
</code></pre></div></div>

<p>Bu kod, en kötü durumda her elemanı diğer elemanlarla karşılaştırır. Karşılaştırma sayısı yaklaşık $n(n-1)/2$ olduğundan zaman karmaşıklığı $O(n^2)$, ek mekan karmaşıklığı ise $O(1)$ olur.</p>

<p>Bir küme kullanarak zamanı iyileştirebiliriz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">tekrar_var_mi</span><span class="p">(</span><span class="n">liste</span><span class="p">):</span>
    <span class="n">gorulenler</span> <span class="o">=</span> <span class="nf">set</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">eleman</span> <span class="ow">in</span> <span class="n">liste</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">eleman</span> <span class="ow">in</span> <span class="n">gorulenler</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">True</span>
        <span class="n">gorulenler</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">eleman</span><span class="p">)</span>
    <span class="k">return</span> <span class="bp">False</span>
</code></pre></div></div>

<p>Kümede arama ve ekleme ortalama $O(1)$ kabul edilir. Bu nedenle toplam süre $O(n)$ seviyesine iner; fakat küme en kötü durumda $n$ mans eleman sakladığı için mekan tüketimi $O(n)$ olur. Yani zamanı kazanırken belleği harcadık.</p>

<h2 id="mekan-karmaşıklığını-unutma">Mekan karmaşıklığını unutma</h2>

<p>Mekan karmaşıklığı,/algo algoritmanın giriş dışında kullandığı ek belleği inceler. Değişkenler, geçici diziler, veri yapıları ve özyinelemeli çağrı yığını hesaba katılmalıdır.</p>

<table>
  <thead>
    <tr>
      <th>ring</th>
      <th style="text-align: right">Yaklaşım</th>
      <th style="text-align: right">Zaman</th>
      <th>Ek mekan</th>
      <th>Tercih nedeni</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td> </td>
      <td style="text-align: right">Çift döngü</td>
      <td style="text-align: right">$O(n-ni^2)$</td>
      <td>$O(1)$</td>
      <td>Bellek çok sınırlıysa</td>
    </tr>
    <tr>
      <td> </td>
      <td style="text-align: right">Küme kullanımı</td>
      <td style="text-align: right">$O(n)$ ortalama</td>
      <td>$O(n)$</td>
      <td>Hız slot betvikiubilrse phrase ya da büyük veri işleniyorsa</td>
    </tr>
  </tbody>
</table>

<p>Özyinelemeli bir fonksiyon da görünürde ek koleksiyon oluşturmasa bile çağrı yığını tüketir. Örneğin dengeli bir ikili ağaçta arama derinliği $O(\log n)$ ise yığın alanı da $O(\log n)$ olabilir.</p>

<p>plant ## En verimli algoritmayı seçme yöntemi</p>

<p>Öncelikle gerçek kısıtları belirle: En büyük girdi kaç elemanlı? Bellek sınırı nedir? Sonuç anlık mı üretilmeli? Ardından aday algoritmaların en kötü, ortalama ve gerekiyorsa en iyi durumlarını karşılaştır.</p>

<p>Küçük $n$ değerlerinde basit bir $O(n^2)$ çözüm, düşük sabit maliyetleri sayesinde yeterli olabilir. Buna karşılık $n=1\,000\,000$ olduğunda karesel bir yaklaşım yaklaşık $10^{12}$ işlem anlamına gelir. Bu noktada $O(n\log n)$ veya $O(n)$ seçenekleri belirgin biçimde avantajlıdır.</p>

<p>Son olarak teorik analizi gerçek ölçümlerle doğrula. Profil çıkarma araçları, önbellek davranışı ve veri dağılımı gibi Big O’nun göstermediği ayrıntıları ortaya çıkarır. En iyi seçim her zaman en küçük notasyon değildir; ihtiyaçları karşılayan, anlaşılır ve kaynak dengesini doğru kuran algoritmadır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Big O" /><category term="algoritma analizi" /><category term="zaman karmaşıklığı" /><summary type="html"><![CDATA[Bir problemi çözen ilk algoritmayı bulmak güzeldir; ancak milyonlarca veri geldiğinde hâlâ çalışan algoritmayı bulmak çok daha güzeldir. Big O notasyonu, farklı algoritmaların veri büyüdükçe nasıl davranacağını karşılaştırmamızı sağlar. Böylece yalnızca çalışan değil, zaman ve bellek açısından sürdürülebilir çözümler seçebiliriz.]]></summary></entry><entry><title type="html">Dinamik Programlamanın Kalbi: Alt Problemler, Durumlar ve Memoization</title><link href="https://sonsuzus.github.io/posts/dinamik-programlamanin-kalbi-alt-problemler-durumlar-ve-memoization/" rel="alternate" type="text/html" title="Dinamik Programlamanın Kalbi: Alt Problemler, Durumlar ve Memoization" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/dinamik-programlamanin-kalbi-alt-problemler-durumlar-ve-memoization</id><content type="html" xml:base="https://sonsuzus.github.io/posts/dinamik-programlamanin-kalbi-alt-problemler-durumlar-ve-memoization/"><![CDATA[<p>Bazı algoritmalar aynı hesabı tekrar tekrar yaparak işlemciyi küçük bir hamster çarkına sokar. Dinamik programlama, bu gereksiz tekrarları fark edip sonuçları saklayan güçlü bir problem çözme yaklaşımıdır. Temel fikir; büyük bir problemi daha küçük alt problemlere ayırmak, her alt problemi doğru biçimde temsil eden durumları tanımlamak ve hesaplanan sonuçları yeniden kullanmaktır.</p>

<p>``</p>

<h2 id="dinamik-programlama-ne-zaman-kullanılır">Dinamik programlama ne zaman kullanılır?</h2>

<p>Bir problemi parçalara bölmek tek başına dinamik programlama değildir. Yaklaşımın etkili olabilmesi için genellikle iki özellik aranır:</p>

<ol>
  <li><strong>Örtüşen alt problemler:</strong> Aynı alt problem farklı hesaplama yollarında tekrar ortaya çıkar.</li>
  <li><strong>Optimal alt yapı:</strong> Büyük problemin en iyi çözümü, alt problemlerin en iyi çözümlerinden oluşturulabilir.</li>
</ol>

<p>Örneğin Fibonacci dizisi şu bağıntıyla tanımlanır:</p>

\[F(n) = F(n-1) + F(n-2)\]

<p>ve başlangıç durumları şöyledir:</p>

\[F(0)=0, \qquad F(1)=1\]

<p>Saf özyinelemeli çözümde <code class="language-plaintext highlighter-rouge">F(n-2)</code> gibi değerler birçok kez hesaplanır. Çağrı ağacı büyüdükçe çalışma süresi yaklaşık $O(2^n)$ seviyesine çıkar. Dinamik programlama sayesinde her değer yalnızca bir kez hesaplanarak süre $O(n)$ olur.</p>

<h2 id="birinci-adım-alt-problemleri-belirlemek">Birinci adım: Alt problemleri belirlemek</h2>

<p>Büyük problemin daha küçük sürümleri alt problem olarak seçilir. Fibonacci örneğinde “<code class="language-plaintext highlighter-rouge">n</code> sayısının Fibonacci değerini bulmak” ana problemse <code class="language-plaintext highlighter-rouge">F(n-1)</code> ve <code class="language-plaintext highlighter-rouge">F(n-2)</code> onun alt problemleridir.</p>

<p>Daha gerçekçi bir örnek olan sırt çantası probleminde ise alt problem yalnızca kaç eşyanın incelendiğiyle açıklanamaz. Kalan kapasite de sonucu etkiler. Bu nedenle alt problemleri tanımlarken gelecekteki kararları etkileyen bütün bilgileri korumak gerekir.</p>

<h2 id="i̇kinci-adım-durumu-tanımlamak">İkinci adım: Durumu tanımlamak</h2>

<p><strong>Durum</strong>, bir alt problemi benzersiz biçimde ifade eden en küçük bilgi kümesidir. İyi durum tanımı, dinamik programlamanın en kritik bölümüdür.</p>

<p>Sırt çantası problemi için şu durum kullanılabilir:</p>

\[DP(i, c) = \text{İlk } i \text{ eşya ve } c \text{ kapasiteyle elde edilen en yüksek değer}\]

<p>Burada <code class="language-plaintext highlighter-rouge">i</code> hangi eşyalara bakabildiğimizi, <code class="language-plaintext highlighter-rouge">c</code> ise kalan kapasiteyi belirtir. Gereksiz bilgi eklemek durum sayısını artırır; eksik bilgi kullanmak ise farklı alt problemleri yanlışlıkla aynı kabul eder.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Sorduğu soru</th>
      <th>Fibonacci örneği</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Alt problem</td>
      <td>Daha küçük hangi problemi çözüyorum?</td>
      <td><code class="language-plaintext highlighter-rouge">F(n-1)</code></td>
    </tr>
    <tr>
      <td>Durum</td>
      <td>Alt problemi hangi bilgiler tanımlar?</td>
      <td><code class="language-plaintext highlighter-rouge">n</code></td>
    </tr>
    <tr>
      <td>Geçiş</td>
      <td>Sonraki sonuç nasıl üretilir?</td>
      <td><code class="language-plaintext highlighter-rouge">F(n-1) + F(n-2)</code></td>
    </tr>
    <tr>
      <td>Başlangıç</td>
      <td>Hesaplamayı nerede durdururum?</td>
      <td><code class="language-plaintext highlighter-rouge">F(0)</code> ve <code class="language-plaintext highlighter-rouge">F(1)</code></td>
    </tr>
  </tbody>
</table>

<h2 id="üçüncü-adım-memoization-ile-tekrarları-önlemek">Üçüncü adım: Memoization ile tekrarları önlemek</h2>

<p>Memoization, yukarıdan aşağıya çalışan özyinelemeli çözümün sonuçlarını bir önbellekte saklar. Fonksiyon aynı durumla yeniden çağrıldığında hesap yapmak yerine kayıtlı sonuç döndürülür.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">memo</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
    <span class="c1"># Sözlük, daha önce çözülen durumların sonuçlarını saklar.
</span>    <span class="k">if</span> <span class="n">memo</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
        <span class="n">memo</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">memo</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">n</span>

    <span class="n">memo</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">memo</span><span class="p">)</span> <span class="o">+</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="n">memo</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">fibonacci</span><span class="p">(</span><span class="mi">40</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu kodda sözlüğün anahtarı durumu, yani <code class="language-plaintext highlighter-rouge">n</code> değerini temsil eder. Her durum bir kez çözüldüğü için toplam $n+1$ farklı durum bulunur. Her durumdaki işlem sabit zamanlı olduğundan karmaşıklık $O(n)$ zaman ve $O(n)$ bellek olur.</p>

<h2 id="memoization-ve-tabulation-farkı">Memoization ve tabulation farkı</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Memoization</th>
      <th>Tabulation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yön</td>
      <td>Yukarıdan aşağıya</td>
      <td>Aşağıdan yukarıya</td>
    </tr>
    <tr>
      <td>Yapı</td>
      <td>Özyineleme</td>
      <td>Döngü</td>
    </tr>
    <tr>
      <td>Hesaplanan durumlar</td>
      <td>Yalnızca ihtiyaç duyulanlar</td>
      <td>Genellikle tüm tablo</td>
    </tr>
    <tr>
      <td>Risk</td>
      <td>Çağrı yığını taşabilir</td>
      <td>Sıralama hatası yapılabilir</td>
    </tr>
  </tbody>
</table>

<p>Dinamik programlama ezberlenecek bir kod kalıbı değil, düşünme disiplinidir: Önce alt problemleri keşfet, sonra durumu mümkün olduğunca sade tanımla, geçiş bağıntısını kur ve tekrarları saklayarak ortadan kaldır. Bu adımlar oturduğunda korkutucu görünen pek çok algoritma, düzenli doldurulan bir tabloya dönüşür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="dinamik programlama" /><category term="algoritmalar" /><category term="memoization" /><summary type="html"><![CDATA[Bazı algoritmalar aynı hesabı tekrar tekrar yaparak işlemciyi küçük bir hamster çarkına sokar. Dinamik programlama, bu gereksiz tekrarları fark edip sonuçları saklayan güçlü bir problem çözme yaklaşımıdır. Temel fikir; büyük bir problemi daha küçük alt problemlere ayırmak, her alt problemi doğru biçimde temsil eden durumları tanımlamak ve hesaplanan sonuçları yeniden kullanmaktır.]]></summary></entry><entry><title type="html">Diziden Kuyruğa: Veri Yapılarıyla Akıllı Problem Çözme</title><link href="https://sonsuzus.github.io/posts/diziden-kuyruga-veri-yapilariyla-akilli-problem-cozme/" rel="alternate" type="text/html" title="Diziden Kuyruğa: Veri Yapılarıyla Akıllı Problem Çözme" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/diziden-kuyruga-veri-yapilariyla-akilli-problem-cozme</id><content type="html" xml:base="https://sonsuzus.github.io/posts/diziden-kuyruga-veri-yapilariyla-akilli-problem-cozme/"><![CDATA[<p>Bir algoritmanın başarısı yalnızca doğru sonucu üretmesine değil, bunu ne kadar hızlı ve az bellek kullanarak yaptığına da bağlıdır. Diziler, bağlı listeler, yığınlar ve kuyruklar bu noktada programcının alet çantasındaki temel araçlardır. Doğru veri yapısını seçmek bazen yüzlerce satır kod yazmaktan daha değerlidir; yanlış seçim ise hızlı görünen bir çözümü kaplumbağaya çevirebilir.
``</p>

<h2 id="veri-yapısı-seçimi-neden-önemlidir">Veri yapısı seçimi neden önemlidir?</h2>

<p>Bir veri yapısını değerlendirirken genellikle zaman ve alan karmaşıklığına bakarız. Bir algoritmanın çalışma süresi, girdi büyüklüğü $n$ arttıkça değişir. Örneğin bir dizinin bütün elemanlarını gezmek $T(n)=an+b$ biçiminde modellenebilir ve bu işlem $O(n)$ karmaşıklığındadır.</p>

<p>Sık kullanılan işlemlerin genel karşılaştırması şöyledir:</p>

<table>
  <thead>
    <tr>
      <th>Veri yapısı</th>
      <th style="text-align: right">İndeksle erişim</th>
      <th style="text-align: right">Başa ekleme</th>
      <th style="text-align: right">Sona ekleme</th>
      <th>Tipik kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dizi</td>
      <td style="text-align: right">$O(1)$</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(1)$ amortize</td>
      <td>Hızlı erişim, sıralı veriler</td>
    </tr>
    <tr>
      <td>Bağlı liste</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td style="text-align: right">$O(1)$*</td>
      <td>Sık ekleme ve silme</td>
    </tr>
    <tr>
      <td>Yığın</td>
      <td style="text-align: right">Yalnızca tepe</td>
      <td style="text-align: right">$O(1)$</td>
      <td style="text-align: right">—</td>
      <td>Geri alma, parantez kontrolü</td>
    </tr>
    <tr>
      <td>Kuyruk</td>
      <td style="text-align: right">Yalnızca ön</td>
      <td style="text-align: right">—</td>
      <td style="text-align: right">$O(1)$</td>
      <td>İş sıralama, genişlik öncelikli arama</td>
    </tr>
  </tbody>
</table>

<p>* Son düğümün adresi ayrıca tutuluyorsa.</p>

<h2 id="diziler-hızlı-erişimin-yıldızı">Diziler: Hızlı erişimin yıldızı</h2>

<p>Diziler elemanları mantıksal olarak yan yana saklar. Bu nedenle $i$ numaralı elemana erişmek için başlangıç adresine belirli bir uzaklık eklemek yeterlidir:</p>

\[adres(i)=başlangıç+i\times eleman\_boyutu\]

<p>Bu hesaplama sabit zamanda yapılır. Sık sık “beşinci eleman nedir?” diye sorulan problemlerde dizi güçlü bir seçimdir. Buna karşılık dizinin başına eleman eklemek, diğer elemanların kaydırılmasını gerektirdiği için pahalıdır.</p>

<p>Örneğin iki işaretçi tekniği, sıralı bir dizide hedef toplamı ararken iç içe döngü ihtiyacını ortadan kaldırır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">hedef_cifti_bul</span><span class="p">(</span><span class="n">sayilar</span><span class="p">,</span> <span class="n">hedef</span><span class="p">):</span>
    <span class="n">sol</span><span class="p">,</span> <span class="n">sag</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">sayilar</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>

    <span class="k">while</span> <span class="n">sol</span> <span class="o">&lt;</span> <span class="n">sag</span><span class="p">:</span>
        <span class="n">toplam</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">[</span><span class="n">sol</span><span class="p">]</span> <span class="o">+</span> <span class="n">sayilar</span><span class="p">[</span><span class="n">sag</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">toplam</span> <span class="o">==</span> <span class="n">hedef</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">sayilar</span><span class="p">[</span><span class="n">sol</span><span class="p">],</span> <span class="n">sayilar</span><span class="p">[</span><span class="n">sag</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">toplam</span> <span class="o">&lt;</span> <span class="n">hedef</span><span class="p">:</span>
            <span class="n">sol</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">sag</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="bp">None</span>
</code></pre></div></div>

<p>Bu kod, sıralı dizinin iki ucundan ilerleyerek uygun çifti bulur. Kaba kuvvet yaklaşımının $O(n^2)$ maliyetini $O(n)$ seviyesine indirir.</p>

<h2 id="bağlı-listeler-esnek-vagonlar">Bağlı listeler: Esnek vagonlar</h2>

<p>Bağlı listeyi, her vagonun bir sonrakinin adresini taşıdığı tren gibi düşünebiliriz. Düğümler bellekte yan yana olmak zorunda değildir. Bir düğüm biliniyorsa araya yeni düğüm eklemek yalnızca bağlantıları değiştirdiği için $O(1)$ sürer.</p>

<p>Ancak belirli bir indekse doğrudan sıçranamaz; düğümler baştan itibaren gezilmelidir. Dolayısıyla rastgele erişimin yoğun olduğu bir problemde bağlı liste kullanmak, kitabın her sayfasını birinciden başlayarak aramaya benzer.</p>

<p>Bağlı listeler; müzik listeleri, tarayıcı geçmişi ve sık ekleme-silme yapılan koleksiyonlar için uygundur. Çift bağlı listeler ileri ve geri hareket sağlarken fazladan işaretçi belleği tüketir.</p>

<h2 id="yığın-son-gelen-ilk-çıkar">Yığın: Son gelen ilk çıkar</h2>

<p>Yığın, $LIFO$ yani “son giren ilk çıkar” ilkesini uygular. Tabakları üst üste koyduğunuzu düşünün: İlk olarak en üstteki tabağı alırsınız. Fonksiyon çağrıları, geri alma işlemleri ve sözdizimi denetimi yığının doğal kullanım alanlarıdır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">parantezler_dengeli_mi</span><span class="p">(</span><span class="n">metin</span><span class="p">):</span>
    <span class="n">yigin</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">eslesme</span> <span class="o">=</span> <span class="p">{</span><span class="sh">'</span><span class="s">)</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">(</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">]</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">[</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">}</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">{</span><span class="sh">'</span><span class="p">}</span>

    <span class="k">for</span> <span class="n">karakter</span> <span class="ow">in</span> <span class="n">metin</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">karakter</span> <span class="ow">in</span> <span class="sh">'</span><span class="s">([{</span><span class="sh">'</span><span class="p">:</span>
            <span class="n">yigin</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">karakter</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">karakter</span> <span class="ow">in</span> <span class="n">eslesme</span><span class="p">:</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">yigin</span> <span class="ow">or</span> <span class="n">yigin</span><span class="p">.</span><span class="nf">pop</span><span class="p">()</span> <span class="o">!=</span> <span class="n">eslesme</span><span class="p">[</span><span class="n">karakter</span><span class="p">]:</span>
                <span class="k">return</span> <span class="bp">False</span>

    <span class="k">return</span> <span class="nf">len</span><span class="p">(</span><span class="n">yigin</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
</code></pre></div></div>

<p>Burada açılan parantezler yığına eklenir; kapanış görüldüğünde en son açılan parantez çıkarılır. Her karakter bir kez işlendiğinden süre $O(n)$, en kötü durumdaki bellek kullanımı da $O(n)$ olur.</p>

<h2 id="kuyruk-sıraya-kaynak-yapmak-yok">Kuyruk: Sıraya kaynak yapmak yok</h2>

<p>Kuyruk $FIFO$, yani “ilk giren ilk çıkar” düzeninde çalışır. Yazdırma görevleri, mesaj sistemleri ve genişlik öncelikli arama bu yapıyı kullanır. Bir grafikte başlangıç düğümüne en yakın noktaları önce keşfetmek istiyorsak kuyruğa komşuları ekler, önden sırayla çıkarırız.</p>

<p>Python’da listenin başından <code class="language-plaintext highlighter-rouge">pop(0)</code> kullanmak $O(n)$ maliyetlidir. Bunun yerine <code class="language-plaintext highlighter-rouge">collections.deque</code> tercih edilmelidir; <code class="language-plaintext highlighter-rouge">append</code> ve <code class="language-plaintext highlighter-rouge">popleft</code> işlemleri $O(1)$ zamanda gerçekleşir.</p>

<h2 id="problem-çözerken-karar-reçetesi">Problem çözerken karar reçetesi</h2>

<p>Önce problemin baskın işlemini belirleyin: İndeksle erişim gerekiyorsa dizi, sık bağlantı değişikliği varsa bağlı liste, en son eklenene dönülecekse yığın, geliş sırası korunacaksa kuyruk düşünün. Ardından en kötü durumu analiz edin ve $n$ iki katına çıktığında maliyetin nasıl değiştiğini sorun. Veri yapısı seçimi ezber değil, problemin davranışını doğru okuma sanatıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="veri yapıları" /><category term="algoritmalar" /><category term="python" /><summary type="html"><![CDATA[Bir algoritmanın başarısı yalnızca doğru sonucu üretmesine değil, bunu ne kadar hızlı ve az bellek kullanarak yaptığına da bağlıdır. Diziler, bağlı listeler, yığınlar ve kuyruklar bu noktada programcının alet çantasındaki temel araçlardır. Doğru veri yapısını seçmek bazen yüzlerce satır kod yazmaktan daha değerlidir; yanlış seçim ise hızlı görünen bir çözümü kaplumbağaya çevirebilir.]]></summary></entry><entry><title type="html">En Kısa Yol Arenası: Dijkstra, Bellman-Ford ve Floyd-Warshall</title><link href="https://sonsuzus.github.io/posts/en-kisa-yol-arenasi-dijkstra-bellman-ford-ve-floyd-warshall/" rel="alternate" type="text/html" title="En Kısa Yol Arenası: Dijkstra, Bellman-Ford ve Floyd-Warshall" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/en-kisa-yol-arenasi-dijkstra-bellman-ford-ve-floyd-warshall</id><content type="html" xml:base="https://sonsuzus.github.io/posts/en-kisa-yol-arenasi-dijkstra-bellman-ford-ve-floyd-warshall/"><![CDATA[<p>Bir şehir haritasında en yakın kafeyi aramak, ağ paketlerini yönlendirmek veya bir oyundaki karaktere güvenli rota çizmek aynı temel soruya dayanır: Bir noktadan diğerine en düşük maliyetle nasıl gideriz? Dijkstra, Bellman-Ford ve Floyd-Warshall bu soruya farklı koşullarda cevap veren üç klasik algoritmadır. Ancak yanlış algoritmayı seçmek, navigasyon uygulamasını macera oyununa çevirebilir!</p>

<p>``</p>

<h2 id="problemin-matematiksel-modeli">Problemin matematiksel modeli</h2>

<p>Bir ağırlıklı grafı $G=(V,E)$ biçiminde tanımlayalım. Burada $V$ düğümleri, $E$ kenarları ve $w(u,v)$ ise $u$ ile $v$ arasındaki geçiş maliyetini gösterir. Bir $P$ yolunun toplam maliyeti:</p>

\[W(P)=\sum_{(u,v)\in P} w(u,v)\]

<p>şeklindedir. Amaç, kaynak $s$ ile hedef $t$ arasındaki yollar içinde maliyeti en küçük olanı bulmaktır:</p>

\[d(s,t)=\min_{P:s\leadsto t} W(P)\]

<p>Kenar ağırlıkları mesafe, süre, ücret veya enerji tüketimi olabilir. Kritik ayrım, negatif ağırlıkların bulunup bulunmamasıdır. Örneğin bir finans modelinde kazanç, negatif maliyet olarak temsil edilebilir.</p>

<h2 id="üç-algoritma-üç-farklı-yaklaşım">Üç algoritma, üç farklı yaklaşım</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Dijkstra</th>
      <th>Bellman-Ford</th>
      <th>Floyd-Warshall</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Hesaplanan yollar</td>
      <td>Tek kaynaktan tüm düğümlere</td>
      <td>Tek kaynaktan tüm düğümlere</td>
      <td>Her düğüm çifti arasında</td>
    </tr>
    <tr>
      <td>Negatif kenar</td>
      <td>Desteklemez</td>
      <td>Destekler</td>
      <td>Destekler</td>
    </tr>
    <tr>
      <td>Negatif döngü tespiti</td>
      <td>Hayır</td>
      <td>Evet</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Zaman karmaşıklığı</td>
      <td>$O((V+E)\log V)$</td>
      <td>$O(VE)$</td>
      <td>$O(V^3)$</td>
    </tr>
    <tr>
      <td>İdeal kullanım</td>
      <td>Büyük ve seyrek graflar</td>
      <td>Negatif maliyetli graflar</td>
      <td>Küçük veya yoğun graflar</td>
    </tr>
  </tbody>
</table>

<h3 id="dijkstra-hızlı-ama-seçici">Dijkstra: Hızlı ama seçici</h3>

<p>Dijkstra, başlangıç düğümünden erişilebilen en düşük geçici mesafeye sahip düğümü sürekli seçer. Açgözlü çalışır: Kesinleştirilen bir mesafeye tekrar dönmez. Bu karar yalnızca tüm ağırlıklar $w(u,v)\geq 0$ olduğunda güvenlidir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">heapq</span>

<span class="k">def</span> <span class="nf">dijkstra</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">source</span><span class="p">):</span>
    <span class="n">dist</span> <span class="o">=</span> <span class="p">{</span><span class="n">node</span><span class="p">:</span> <span class="nf">float</span><span class="p">(</span><span class="sh">'</span><span class="s">inf</span><span class="sh">'</span><span class="p">)</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">}</span>
    <span class="n">dist</span><span class="p">[</span><span class="n">source</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">queue</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="n">source</span><span class="p">)]</span>

    <span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
        <span class="n">current</span><span class="p">,</span> <span class="n">node</span> <span class="o">=</span> <span class="n">heapq</span><span class="p">.</span><span class="nf">heappop</span><span class="p">(</span><span class="n">queue</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">current</span> <span class="o">!=</span> <span class="n">dist</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
            <span class="k">continue</span>
        <span class="k">for</span> <span class="n">neighbor</span><span class="p">,</span> <span class="n">weight</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
            <span class="n">candidate</span> <span class="o">=</span> <span class="n">current</span> <span class="o">+</span> <span class="n">weight</span>
            <span class="k">if</span> <span class="n">candidate</span> <span class="o">&lt;</span> <span class="n">dist</span><span class="p">[</span><span class="n">neighbor</span><span class="p">]:</span>
                <span class="n">dist</span><span class="p">[</span><span class="n">neighbor</span><span class="p">]</span> <span class="o">=</span> <span class="n">candidate</span>
                <span class="n">heapq</span><span class="p">.</span><span class="nf">heappush</span><span class="p">(</span><span class="n">queue</span><span class="p">,</span> <span class="p">(</span><span class="n">candidate</span><span class="p">,</span> <span class="n">neighbor</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">dist</span>
</code></pre></div></div>

<p>Öncelik kuyruğu, sıradaki en yakın düğümü verimli biçimde seçer. Yol ağları ve internet yönlendirme senaryoları için genellikle en pratik tercihtir.</p>

<h3 id="bellman-ford-yavaş-ama-kuşkucu">Bellman-Ford: Yavaş ama kuşkucu</h3>

<table>
  <tbody>
    <tr>
      <td>Bellman-Ford bütün kenarları en fazla $</td>
      <td>V</td>
      <td>-1$ tur gevşetir. Gevşetme işlemi şu eşitsizliği kontrol eder:</td>
    </tr>
  </tbody>
</table>

\[d(v)&gt;d(u)+w(u,v)\]

<p>Koşul doğruysa $d(v)$ güncellenir. Bir tur daha yapıldığında hâlâ güncelleme gerçekleşiyorsa erişilebilir bir negatif döngü vardır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">bellman_ford</span><span class="p">(</span><span class="n">vertices</span><span class="p">,</span> <span class="n">edges</span><span class="p">,</span> <span class="n">source</span><span class="p">):</span>
    <span class="n">dist</span> <span class="o">=</span> <span class="p">{</span><span class="n">v</span><span class="p">:</span> <span class="nf">float</span><span class="p">(</span><span class="sh">'</span><span class="s">inf</span><span class="sh">'</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vertices</span><span class="p">}</span>
    <span class="n">dist</span><span class="p">[</span><span class="n">source</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">vertices</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">):</span>
        <span class="n">changed</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="k">for</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">weight</span> <span class="ow">in</span> <span class="n">edges</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">dist</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">+</span> <span class="n">weight</span> <span class="o">&lt;</span> <span class="n">dist</span><span class="p">[</span><span class="n">v</span><span class="p">]:</span>
                <span class="n">dist</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">+</span> <span class="n">weight</span>
                <span class="n">changed</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">changed</span><span class="p">:</span>
            <span class="k">break</span>

    <span class="k">for</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">weight</span> <span class="ow">in</span> <span class="n">edges</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">dist</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">+</span> <span class="n">weight</span> <span class="o">&lt;</span> <span class="n">dist</span><span class="p">[</span><span class="n">v</span><span class="p">]:</span>
            <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">'</span><span class="s">Negatif döngü bulundu</span><span class="sh">'</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">dist</span>
</code></pre></div></div>

<p>Döviz arbitrajı ve maliyetlerin negatif olabildiği modeller, ek işlem süresine rağmen Bellman-Ford için uygundur.</p>

<h3 id="floyd-warshall-herkes-herkese-karşı">Floyd-Warshall: Herkes herkese karşı</h3>

<p>Floyd-Warshall, dinamik programlama kullanır. $k$ ara düğümüne izin verildiğinde güncelleme kuralı şöyledir:</p>

\[D_{ij}=\min(D_{ij},D_{ik}+D_{kj})\]

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">floyd_warshall</span><span class="p">(</span><span class="n">dist</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">dist</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
                <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">dist</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">])</span>
    <span class="k">return</span> <span class="n">dist</span>
</code></pre></div></div>

<p>Sonuç matrisindeki herhangi bir $D_{ii}&lt;0$ değeri negatif döngüyü gösterir. Bellek maliyeti $O(V^2)$ olduğundan devasa graflarda pahalıdır; fakat tüm çiftlerin sorgulanacağı küçük ulaşım veya ilişki ağlarında son derece kullanışlıdır.</p>

<h2 id="hangisini-seçmeliyiz">Hangisini seçmeliyiz?</h2>

<p>Negatif ağırlık yoksa ve tek kaynak önemliyse <strong>Dijkstra</strong>, negatif kenarlar varsa <strong>Bellman-Ford</strong>, bütün düğüm çiftleri gerekiyorsa <strong>Floyd-Warshall</strong> seçilmelidir. Özetle Dijkstra sprinter, Bellman-Ford temkinli denetçi, Floyd-Warshall ise herkesin rotasını önceden çıkaran takıntılı haritacıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="graf algoritmaları" /><category term="en kısa yol" /><category term="Python" /><summary type="html"><![CDATA[Bir şehir haritasında en yakın kafeyi aramak, ağ paketlerini yönlendirmek veya bir oyundaki karaktere güvenli rota çizmek aynı temel soruya dayanır: Bir noktadan diğerine en düşük maliyetle nasıl gideriz? Dijkstra, Bellman-Ford ve Floyd-Warshall bu soruya farklı koşullarda cevap veren üç klasik algoritmadır. Ancak yanlış algoritmayı seçmek, navigasyon uygulamasını macera oyununa çevirebilir!]]></summary></entry><entry><title type="html">Graflar ve Ağaçlarda DFS ve BFS: Derine mi, Genişe mi?</title><link href="https://sonsuzus.github.io/posts/graflar-ve-agaclarda-dfs-ve-bfs-derine-mi-genise-mi/" rel="alternate" type="text/html" title="Graflar ve Ağaçlarda DFS ve BFS: Derine mi, Genişe mi?" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/graflar-ve-agaclarda-dfs-ve-bfs-derine-mi-genise-mi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/graflar-ve-agaclarda-dfs-ve-bfs-derine-mi-genise-mi/"><![CDATA[<p>Bir labirentte çıkış aradığınızı düşünün: Bir yolu sonuna kadar takip edip çıkmazda geri mi dönersiniz, yoksa önce size bir adım uzaklıktaki bütün yolları mı incelersiniz? İlk yaklaşım <strong>derinlik öncelikli arama (DFS)</strong>, ikincisi ise <strong>genişlik öncelikli arama (BFS)</strong> mantığıdır. Bu iki kapsamlı arama tekniği; ağaçların, grafların ve birçok yapay zekâ probleminin temel araçlarıdır.
``</p>
<h2 id="önce-yapıyı-tanıyalım">Önce yapıyı tanıyalım</h2>

<p>Bir <strong>graf</strong>, düğümlerden ve bu düğümleri bağlayan kenarlardan oluşur: $G=(V,E)$. Burada $V$ düğüm, $E$ ise kenar kümesidir. Ağaç da çevrim içermeyen, bağlantılı özel bir graftır. Bir ağaçta iki düğüm arasında yalnızca tek bir basit yol bulunurken genel bir grafta birden fazla yol ve çevrim olabilir.</p>

<p>Bu ayrım uygulamada önemlidir. Ağaç üzerinde aşağı doğru ilerlemek çoğunlukla güvenlidir; ancak çevrimli bir grafta ziyaret edilen düğümler kaydedilmezse algoritma <code class="language-plaintext highlighter-rouge">A → B → A → B</code> döngüsünde sonsuza kadar kalabilir.</p>

<h2 id="derinlik-öncelikli-arama-yolun-sonunu-gör">Derinlik öncelikli arama: Yolun sonunu gör</h2>

<p>DFS, başlangıç düğümünden hareket ederek erişebildiği en derin noktaya ilerler. Gidecek yeni komşu kalmadığında geri izleme yapar. Bu davranış doğal olarak bir <strong>yığın (stack)</strong> ile modellenir. Özyinelemeli fonksiyonlarda çağrı yığını aynı görevi üstlenir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">dfs</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">start</span><span class="p">):</span>
    <span class="n">visited</span> <span class="o">=</span> <span class="nf">set</span><span class="p">()</span>
    <span class="n">stack</span> <span class="o">=</span> <span class="p">[</span><span class="n">start</span><span class="p">]</span>

    <span class="k">while</span> <span class="n">stack</span><span class="p">:</span>
        <span class="n">node</span> <span class="o">=</span> <span class="n">stack</span><span class="p">.</span><span class="nf">pop</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="n">visited</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>  <span class="c1"># Düğüm burada işlenir.
</span>
        <span class="c1"># Ters ekleme, soldaki komşunun önce gezilmesini sağlar.
</span>        <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="nf">reversed</span><span class="p">(</span><span class="n">graph</span><span class="p">[</span><span class="n">node</span><span class="p">]):</span>
            <span class="k">if</span> <span class="n">neighbor</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
                <span class="n">stack</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">neighbor</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">visited</span>
</code></pre></div></div>

<p>Kod, sıradaki düğümü yığının sonundan alır. Komşular yığına eklendiği için algoritma diğer seçeneklere geçmeden önce bir dal boyunca derinleşir. DFS; çevrim tespiti, topolojik sıralama, bağlı bileşen bulma ve labirent çözme gibi problemlerde kullanışlıdır.</p>

<h2 id="genişlik-öncelikli-arama-katman-katman-ilerle">Genişlik öncelikli arama: Katman katman ilerle</h2>

<p>BFS, önce başlangıç düğümüne bir kenar uzaklıktaki düğümleri, ardından iki kenar uzaklıktakileri inceler. Bu nedenle <strong>kuyruk (queue)</strong> kullanır. Ağırlıksız bir grafta en kısa yolu bulabilmesinin nedeni de düğümleri artan uzaklık sırasıyla ziyaret etmesidir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">collections</span> <span class="kn">import</span> <span class="n">deque</span>

<span class="k">def</span> <span class="nf">bfs</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">start</span><span class="p">):</span>
    <span class="n">visited</span> <span class="o">=</span> <span class="p">{</span><span class="n">start</span><span class="p">}</span>
    <span class="n">queue</span> <span class="o">=</span> <span class="nf">deque</span><span class="p">([(</span><span class="n">start</span><span class="p">,</span> <span class="mi">0</span><span class="p">)])</span>

    <span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
        <span class="n">node</span><span class="p">,</span> <span class="n">distance</span> <span class="o">=</span> <span class="n">queue</span><span class="p">.</span><span class="nf">popleft</span><span class="p">()</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">distance</span><span class="p">)</span>  <span class="c1"># Başlangıca olan uzaklık.
</span>
        <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
            <span class="k">if</span> <span class="n">neighbor</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
                <span class="n">visited</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">neighbor</span><span class="p">)</span>
                <span class="n">queue</span><span class="p">.</span><span class="nf">append</span><span class="p">((</span><span class="n">neighbor</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>

    <span class="k">return</span> <span class="n">visited</span>
</code></pre></div></div>

<p>Bir düğüm kuyruğa eklenirken ziyaret edilmiş sayılır. Böylece aynı düğümün farklı komşular tarafından kuyruğa defalarca eklenmesi önlenir.</p>

<h2 id="dfs-ve-bfs-karşılaştırması">DFS ve BFS karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>DFS</th>
      <th>BFS</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Temel veri yapısı</td>
      <td>Yığın</td>
      <td>Kuyruk</td>
    </tr>
    <tr>
      <td>İlerleme biçimi</td>
      <td>Dal boyunca derine</td>
      <td>Seviye seviye</td>
    </tr>
    <tr>
      <td>Ağırlıksız en kısa yol</td>
      <td>Garanti etmez</td>
      <td>Garanti eder</td>
    </tr>
    <tr>
      <td>Bellek davranışı</td>
      <td>Derinliğe bağlıdır</td>
      <td>Geniş seviyelerde büyür</td>
    </tr>
    <tr>
      <td>Tipik kullanım</td>
      <td>Çevrim, bileşen, topolojik sıralama</td>
      <td>En kısa yol, seviye analizi</td>
    </tr>
    <tr>
      <td>Tamlık</td>
      <td>Sonsuz derinlikte sorun yaşayabilir</td>
      <td>Sonlu dallanmada çözümü bulur</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody>
    <tr>
      <td>Komşuluk listesi kullanılan bir grafta her düğüm ve kenar en fazla sabit sayıda işlendiği için iki algoritmanın zaman karmaşıklığı da $O(</td>
      <td>V</td>
      <td>+</td>
      <td>E</td>
      <td>)$ olur. Bellek karmaşıklığı genel durumda $O(</td>
      <td>V</td>
      <td>)$ düzeyindedir.</td>
    </tr>
  </tbody>
</table>

<p>Arama ağacının dallanma katsayısı $b$, çözüm derinliği $d$ ise BFS yaklaşık $1+b+b^2+…+b^d$ düğüm üretir; baskın terim nedeniyle bu miktar $O(b^d)$ kabul edilir. DFS ise aynı anda çoğunlukla tek yol ile alternatifleri tuttuğundan bellekte daha tutumlu olabilir.</p>

<h2 id="hangisini-seçmeliyiz">Hangisini seçmeliyiz?</h2>

<p>Hedefin başlangıca yakın olduğu veya ağırlıksız en kısa yolun istendiği durumlarda BFS güçlü seçimdir. Arama alanı çok genişse, çözümün derinde olduğu düşünülüyorsa ya da bütün yapısal ilişkiler araştırılacaksa DFS daha uygun olabilir. Ancak kenarlar farklı ağırlıklara sahipse BFS yerine Dijkstra gibi algoritmalar gerekir.</p>

<p>Özetle DFS meraklı bir mağara kâşifi gibi tek tünele dalar; BFS ise düzenli bir arama ekibi gibi bütün katmanı tarar. Doğru algoritma, yalnızca grafın biçimine değil, aradığınız cevabın türüne ve kullanabileceğiniz belleğe de bağlıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="DFS" /><category term="BFS" /><category term="graf algoritmaları" /><summary type="html"><![CDATA[Bir labirentte çıkış aradığınızı düşünün: Bir yolu sonuna kadar takip edip çıkmazda geri mi dönersiniz, yoksa önce size bir adım uzaklıktaki bütün yolları mı incelersiniz? İlk yaklaşım derinlik öncelikli arama (DFS), ikincisi ise genişlik öncelikli arama (BFS) mantığıdır. Bu iki kapsamlı arama tekniği; ağaçların, grafların ve birçok yapay zekâ probleminin temel araçlarıdır.]]></summary></entry><entry><title type="html">İkili Arama ve İki İşaretçi: Arama Tekniklerini Senaryoya Uyarlamak</title><link href="https://sonsuzus.github.io/posts/ikili-arama-ve-iki-isaretci-arama-tekniklerini-senaryoya-uyarlamak/" rel="alternate" type="text/html" title="İkili Arama ve İki İşaretçi: Arama Tekniklerini Senaryoya Uyarlamak" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/ikili-arama-ve-iki-isaretci-arama-tekniklerini-senaryoya-uyarlamak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/ikili-arama-ve-iki-isaretci-arama-tekniklerini-senaryoya-uyarlamak/"><![CDATA[<p>Bir dizide değer bulmak kolay görünebilir; ancak veri büyüdükçe doğrusal arama, samanlıkta iğne aramaya dönüşür. İkili arama ve iki işaretçi tekniği, yalnızca ezberlenecek kod kalıpları değil, farklı problemlere uyarlanabilen düşünme biçimleridir. Biri arama uzayını sürekli yarıya indirirken diğeri iki konumu koordineli hareket ettirerek gereksiz denemeleri ortadan kaldırır.</p>

<p>``</p>

<h2 id="i̇kili-aramanın-temel-mantığı">İkili aramanın temel mantığı</h2>

<p>İkili arama, sıralı bir veri kümesinin ortasındaki elemanı inceler. Aranan değer daha küçükse sağ yarıyı, daha büyükse sol yarıyı eler. Her adımda problem boyutu yarıya indiği için zaman karmaşıklığı:</p>

\[T(n)=T(n/2)+O(1)=O(\log n)\]

<p>şeklindedir. Örneğin yaklaşık bir milyon elemanda doğrusal arama bir milyon karşılaştırma yapabilirken ikili arama yaklaşık $\log_2(1.000.000)\approx20$ adımda sonuca ulaşır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">binary_search</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>

    <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">:</span>
        <span class="n">middle</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>

        <span class="k">if</span> <span class="n">numbers</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">==</span> <span class="n">target</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">middle</span>
        <span class="k">if</span> <span class="n">numbers</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">:</span>
            <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
</code></pre></div></div>

<p>Bu kod, sıralı dizide hedefin indeksini bulur. <code class="language-plaintext highlighter-rouge">left &lt;= right</code> koşulu tek elemanlık son aralığın da kontrol edilmesini sağlar.</p>

<h2 id="sadece-eleman-değil-sınır-aramak">Sadece eleman değil, sınır aramak</h2>

<p>İkili arama çoğu zaman “değer var mı?” sorusundan fazlasını çözer. Tekrarlı elemanlarda ilk konumu, son konumu veya belirli bir koşulu sağlayan en küçük değeri bulabiliriz. Örneğin <code class="language-plaintext highlighter-rouge">[2, 4, 4, 4, 9]</code> dizisinde ilk <code class="language-plaintext highlighter-rouge">4</code> aranırken eşitlikte durmak yerine sonucu kaydedip sola devam ederiz.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">first_position</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="n">answer</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>

    <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">:</span>
        <span class="n">middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">left</span> <span class="o">+</span> <span class="n">right</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="n">numbers</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">numbers</span><span class="p">[</span><span class="n">middle</span><span class="p">]</span> <span class="o">==</span> <span class="n">target</span><span class="p">:</span>
                <span class="n">answer</span> <span class="o">=</span> <span class="n">middle</span>
            <span class="n">right</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">left</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">answer</span>
</code></pre></div></div>

<p>Aynı fikir “en az kaç sunucu gerekli?” veya “bir işi tamamlamaya yeten minimum kapasite nedir?” gibi cevap üzerinde arama problemlerine uygulanır. Buradaki kritik şart, kontrol fonksiyonunun monoton olmasıdır: Bir kapasite yeterliyse daha büyük kapasiteler de yeterli olmalıdır. Böylece sonuçlar <code class="language-plaintext highlighter-rouge">yanlış, yanlış, doğru, doğru</code> biçiminde ayrılır ve geçiş noktası ikili aramayla bulunur.</p>

<h2 id="i̇ki-işaretçi-tekniği">İki işaretçi tekniği</h2>

<p>İki işaretçi, dizinin farklı bölgelerini temsil eden iki indeks kullanır. İşaretçiler karşılıklı yaklaşabilir veya aynı yönde farklı hızlarla ilerleyebilir.</p>

<table>
  <thead>
    <tr>
      <th>Senaryo</th>
      <th>Başlangıç</th>
      <th>Hareket</th>
      <th>Kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sıralı dizide hedef toplam</td>
      <td>İki uç</td>
      <td>Birbirine doğru</td>
      <td>İkili toplam</td>
    </tr>
    <tr>
      <td>Tekrarları kaldırma</td>
      <td>Aynı taraf</td>
      <td>Aynı yönde</td>
      <td>Yerinde düzenleme</td>
    </tr>
    <tr>
      <td>Palindrom kontrolü</td>
      <td>İki uç</td>
      <td>Birbirine doğru</td>
      <td>Simetri testi</td>
    </tr>
    <tr>
      <td>Kayan pencere</td>
      <td>Aynı taraf</td>
      <td>Koşula göre</td>
      <td>Alt dizi problemleri</td>
    </tr>
  </tbody>
</table>

<p>Sıralı dizide toplamı hedefe eşit iki sayı bulalım:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">find_pair</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>

    <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">:</span>
        <span class="n">current</span> <span class="o">=</span> <span class="n">numbers</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">numbers</span><span class="p">[</span><span class="n">right</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">current</span> <span class="o">==</span> <span class="n">target</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">numbers</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">numbers</span><span class="p">[</span><span class="n">right</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">current</span> <span class="o">&lt;</span> <span class="n">target</span><span class="p">:</span>
            <span class="n">left</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">right</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="bp">None</span>
</code></pre></div></div>

<p>Toplam küçükse sol işaretçiyi ilerletmek toplamı büyütür; büyükse sağ işaretçiyi geriletmek toplamı küçültür. Böylece $O(n^2)$ olabilecek tüm çiftleri denemek yerine yalnızca $O(n)$ adım kullanılır.</p>

<h2 id="hangisini-seçmeliyiz">Hangisini seçmeliyiz?</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>İkili arama</th>
      <th>İki işaretçi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Temel gereksinim</td>
      <td>Sıralılık veya monotonluk</td>
      <td>Düzenli hareket kuralı</td>
    </tr>
    <tr>
      <td>Tipik karmaşıklık</td>
      <td>$O(\log n)$</td>
      <td>$O(n)$</td>
    </tr>
    <tr>
      <td>Ana fikir</td>
      <td>Arama alanını yarıya indirmek</td>
      <td>Gereksiz çiftleri elemek</td>
    </tr>
  </tbody>
</table>

<p>Bir problemde önce “Sonuçlar monoton mu?” diye sorulmalıdır; cevap evetse ikili arama güçlü bir adaydır. “İki sınırı hareket ettirerek seçenekleri güvenle eleyebilir miyim?” sorusunun cevabı evetse iki işaretçi düşünülmelidir. Asıl ustalık kodu ezberlemek değil, hangi hareketin neden güvenli olduğunu kanıtlamaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="algoritmalar" /><category term="ikili arama" /><category term="iki işaretçi" /><summary type="html"><![CDATA[Bir dizide değer bulmak kolay görünebilir; ancak veri büyüdükçe doğrusal arama, samanlıkta iğne aramaya dönüşür. İkili arama ve iki işaretçi tekniği, yalnızca ezberlenecek kod kalıpları değil, farklı problemlere uyarlanabilen düşünme biçimleridir. Biri arama uzayını sürekli yarıya indirirken diğeri iki konumu koordineli hareket ettirerek gereksiz denemeleri ortadan kaldırır.]]></summary></entry><entry><title type="html">Özyinelemeden Geri İzlemeye: Labirent ve Tahta Problemlerini Çözmek</title><link href="https://sonsuzus.github.io/posts/ozyinelemeden-geri-izlemeye-labirent-ve-tahta-problemlerini-cozmek/" rel="alternate" type="text/html" title="Özyinelemeden Geri İzlemeye: Labirent ve Tahta Problemlerini Çözmek" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/ozyinelemeden-geri-izlemeye-labirent-ve-tahta-problemlerini-cozmek</id><content type="html" xml:base="https://sonsuzus.github.io/posts/ozyinelemeden-geri-izlemeye-labirent-ve-tahta-problemlerini-cozmek/"><![CDATA[<p>Bir labirentin girişinde durduğunuzu düşünün: Her kavşakta bir yön seçiyor, çıkmaza girerseniz son karar noktasına dönüyorsunuz. Özyinelemeli düşünme ve geri izleme tam olarak böyle çalışır. Büyük bir problemi daha küçük benzer problemlere ayırır, olası seçimleri dener ve başarısız seçimlerden vazgeçerek çözümü sistematik biçimde arar.
``</p>
<h2 id="özyinelemeli-düşünmek-ne-demektir">Özyinelemeli düşünmek ne demektir?</h2>

<p>Özyineleme, bir fonksiyonun problemi küçülterek kendisini çağırmasıdır. Sağlıklı bir özyinelemeli çözümün iki temel parçası bulunur:</p>

<ol>
  <li><strong>Temel durum:</strong> Çağrıların duracağı en küçük problem.</li>
  <li><strong>Özyinelemeli durum:</strong> Problemi daha küçük bir örneğe dönüştüren adım.</li>
</ol>

<p>Örneğin faktöriyel şu bağıntıyla tanımlanır:</p>

\[n! = n \cdot (n-1)!\]

<p>Temel durum ise $0! = 1$ olur. Kod karşılığı oldukça doğaldır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">faktoriyel</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>          <span class="c1"># Temel durum
</span>        <span class="k">return</span> <span class="mi">1</span>
    <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="nf">faktoriyel</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>

<p>Buradaki kritik fikir, fonksiyonun sonsuza kadar çağrılmamasıdır. Her çağrı problemi temel duruma yaklaştırmalıdır. Aksi hâlde çağrı yığını büyür ve program sonunda hata verir.</p>

<h2 id="özyineleme-ile-geri-izleme-arasındaki-fark">Özyineleme ile geri izleme arasındaki fark</h2>

<p>Geri izleme, çoğunlukla özyineleme kullanır; ancak her özyinelemeli algoritma geri izleme değildir. Geri izlemede bir seçim yapılır, sonuç araştırılır ve seçim başarısızsa durum eski hâline getirilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Temel hareket</th>
      <th>Önceki duruma dönüş</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Özyineleme</td>
      <td>Problemi küçültür</td>
      <td>Her zaman gerekli değildir</td>
      <td>Faktöriyel</td>
    </tr>
    <tr>
      <td>Geri izleme</td>
      <td>Seç, araştır, geri al</td>
      <td>Çözüm bulunamazsa gerekir</td>
      <td>Sudoku</td>
    </tr>
    <tr>
      <td>Kaba kuvvet</td>
      <td>Tüm olasılıkları dener</td>
      <td>Genellikle sistemsizdir</td>
      <td>Tüm kombinasyonlar</td>
    </tr>
    <tr>
      <td>Dinamik programlama</td>
      <td>Sonuçları saklar</td>
      <td>Aynı hesabı tekrar etmez</td>
      <td>Fibonacci</td>
    </tr>
  </tbody>
</table>

<p>Geri izlemenin özeti şu üç komuttur: <strong>Seç, keşfet, seçimi geri al.</strong> Bu son adım unutulursa algoritma, önceki yolun izlerini sonraki denemelere taşır.</p>

<h2 id="labirentte-yol-bulma">Labirentte yol bulma</h2>

<p>Bir hücreden yukarı, aşağı, sağa veya sola gidebildiğimizi varsayalım. Duvarlara ve daha önce ziyaret edilen hücrelere giremeyiz. Aşağıdaki fonksiyon, çıkışa ulaştığında <code class="language-plaintext highlighter-rouge">True</code> döndürür:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">yolu_bul</span><span class="p">(</span><span class="n">labirent</span><span class="p">,</span> <span class="n">satir</span><span class="p">,</span> <span class="n">sutun</span><span class="p">,</span> <span class="n">cikis</span><span class="p">,</span> <span class="n">ziyaret</span><span class="p">):</span>
    <span class="nf">if </span><span class="p">(</span><span class="n">satir</span><span class="p">,</span> <span class="n">sutun</span><span class="p">)</span> <span class="o">==</span> <span class="n">cikis</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>

    <span class="nf">if </span><span class="p">(</span><span class="n">satir</span><span class="p">,</span> <span class="n">sutun</span><span class="p">)</span> <span class="ow">in</span> <span class="n">ziyaret</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>

    <span class="k">if</span> <span class="n">labirent</span><span class="p">[</span><span class="n">satir</span><span class="p">][</span><span class="n">sutun</span><span class="p">]</span> <span class="o">==</span> <span class="sh">"</span><span class="s">#</span><span class="sh">"</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>

    <span class="n">ziyaret</span><span class="p">.</span><span class="nf">add</span><span class="p">((</span><span class="n">satir</span><span class="p">,</span> <span class="n">sutun</span><span class="p">))</span>

    <span class="k">for</span> <span class="n">ds</span><span class="p">,</span> <span class="n">dt</span> <span class="ow">in</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)]:</span>
        <span class="n">yeni_s</span><span class="p">,</span> <span class="n">yeni_t</span> <span class="o">=</span> <span class="n">satir</span> <span class="o">+</span> <span class="n">ds</span><span class="p">,</span> <span class="n">sutun</span> <span class="o">+</span> <span class="n">dt</span>
        <span class="k">if</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">yeni_s</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">labirent</span><span class="p">)</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">yeni_t</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">labirent</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
            <span class="k">if</span> <span class="nf">yolu_bul</span><span class="p">(</span><span class="n">labirent</span><span class="p">,</span> <span class="n">yeni_s</span><span class="p">,</span> <span class="n">yeni_t</span><span class="p">,</span> <span class="n">cikis</span><span class="p">,</span> <span class="n">ziyaret</span><span class="p">):</span>
                <span class="k">return</span> <span class="bp">True</span>

    <span class="n">ziyaret</span><span class="p">.</span><span class="nf">remove</span><span class="p">((</span><span class="n">satir</span><span class="p">,</span> <span class="n">sutun</span><span class="p">))</span>  <span class="c1"># Geri izleme
</span>    <span class="k">return</span> <span class="bp">False</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">ziyaret</code> kümesi döngüleri önler. Hücreden çıkışa ulaşılamazsa hücre kümeden silinir; böylece farklı bir yol aynı hücreyi başka bağlamda deneyebilir. Yalnızca herhangi bir yolu arıyorsak hücreyi silmemek de mümkündür. Ancak tüm yolları üretmek istediğimizde geri alma adımı zorunludur.</p>

<h2 id="tahta-doldurma-n-vezir-problemi">Tahta doldurma: N-Vezir problemi</h2>

<p>N-Vezir probleminde $N \times N$ tahtaya, birbirini tehdit etmeyen $N$ vezir yerleştirilir. Her satıra bir vezir koyup yalnızca güvenli sütunları denemek, arama alanını ciddi ölçüde küçültür.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">vezirleri_yerlestir</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">satir</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">sutunlar</span><span class="o">=</span><span class="nf">set</span><span class="p">(),</span> <span class="n">capraz1</span><span class="o">=</span><span class="nf">set</span><span class="p">(),</span> <span class="n">capraz2</span><span class="o">=</span><span class="nf">set</span><span class="p">()):</span>
    <span class="k">if</span> <span class="n">satir</span> <span class="o">==</span> <span class="n">n</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>

    <span class="k">for</span> <span class="n">sutun</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">sutun</span> <span class="ow">in</span> <span class="n">sutunlar</span> <span class="ow">or</span> <span class="n">satir</span> <span class="o">-</span> <span class="n">sutun</span> <span class="ow">in</span> <span class="n">capraz1</span> <span class="ow">or</span> <span class="n">satir</span> <span class="o">+</span> <span class="n">sutun</span> <span class="ow">in</span> <span class="n">capraz2</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="n">sutunlar</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">sutun</span><span class="p">)</span>
        <span class="n">capraz1</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">satir</span> <span class="o">-</span> <span class="n">sutun</span><span class="p">)</span>
        <span class="n">capraz2</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">satir</span> <span class="o">+</span> <span class="n">sutun</span><span class="p">)</span>

        <span class="k">if</span> <span class="nf">vezirleri_yerlestir</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">satir</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">sutunlar</span><span class="p">,</span> <span class="n">capraz1</span><span class="p">,</span> <span class="n">capraz2</span><span class="p">):</span>
            <span class="k">return</span> <span class="bp">True</span>

        <span class="n">sutunlar</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">sutun</span><span class="p">)</span>
        <span class="n">capraz1</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">satir</span> <span class="o">-</span> <span class="n">sutun</span><span class="p">)</span>
        <span class="n">capraz2</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">satir</span> <span class="o">+</span> <span class="n">sutun</span><span class="p">)</span>

    <span class="k">return</span> <span class="bp">False</span>
</code></pre></div></div>

<p>Saf denemede olasılık sayısı yaklaşık $N^N$ olabilir. Geçersiz dalları erkenden budamak ise gereksiz çağrıları engeller. Bu nedenle iyi bir geri izleme çözümünün sırrı yalnızca geri dönmek değil, <strong>ne zaman devam etmemek gerektiğini</strong> erkenden bilmektir.</p>

<p>Özyinelemeli düşünürken önce temel durumu, ardından seçimi ve son olarak geri alma işlemini yazmak yararlıdır. Labirent, Sudoku, N-Vezir ve kelime bulmacaları farklı görünse de aynı macerayı anlatır: Bir kapıyı aç, içeri bak; hazine yoksa kapıyı kapat ve diğerini dene.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="özyineleme" /><category term="geri izleme" /><category term="algoritmalar" /><summary type="html"><![CDATA[Bir labirentin girişinde durduğunuzu düşünün: Her kavşakta bir yön seçiyor, çıkmaza girerseniz son karar noktasına dönüyorsunuz. Özyinelemeli düşünme ve geri izleme tam olarak böyle çalışır. Büyük bir problemi daha küçük benzer problemlere ayırır, olası seçimleri dener ve başarısız seçimlerden vazgeçerek çözümü sistematik biçimde arar.]]></summary></entry><entry><title type="html">Sıralama Algoritmalarının İç İşleyişi: Hangi Durumda Hangisi Daha Hızlı?</title><link href="https://sonsuzus.github.io/posts/siralama-algoritmalarinin-ic-isleyisi-hangi-durumda-hangisi-daha-hizli/" rel="alternate" type="text/html" title="Sıralama Algoritmalarının İç İşleyişi: Hangi Durumda Hangisi Daha Hızlı?" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/siralama-algoritmalarinin-ic-isleyisi-hangi-durumda-hangisi-daha-hizli</id><content type="html" xml:base="https://sonsuzus.github.io/posts/siralama-algoritmalarinin-ic-isleyisi-hangi-durumda-hangisi-daha-hizli/"><![CDATA[<p>Bir veri kümesini sıralamak, programlamanın “çorapları renklerine göre ayırma” problemidir: sonuç basit görünür, fakat doğru yöntem seçilmezse işlem gereksiz yere uzar. Bubble Sort, Merge Sort, Quick Sort ve Heap Sort aynı çıktıyı üretse de bunu yaparken farklı miktarda zaman, bellek ve karşılaştırma harcar. Optimizasyon sorularını çözebilmek için algoritmaların yalnızca karmaşıklıklarını ezberlemek değil, içeride nasıl çalıştıklarını anlamak gerekir.
``</p>
<h2 id="performansı-nasıl-ölçeriz">Performansı nasıl ölçeriz?</h2>

<p>Bir sıralama algoritmasının maliyeti çoğunlukla karşılaştırma ve yer değiştirme sayısıyla değerlendirilir. Girdi boyutu $n$ ise iki iç içe döngü kullanan basit algoritmalar genellikle</p>

\[T(n) \approx \frac{n(n-1)}{2} = O(n^2)\]

<p>karşılaştırma yapar. Böl ve yönet yaklaşımında veri her adımda iki parçaya ayrılır. Yaklaşık $\log_2 n$ seviye oluşur ve her seviyede $n$ eleman işlendiği için maliyet $O(n\log n)$ olur.</p>

<table>
  <thead>
    <tr>
      <th>Algoritma</th>
      <th style="text-align: right">En iyi</th>
      <th style="text-align: right">Ortalama</th>
      <th style="text-align: right">En kötü</th>
      <th style="text-align: right">Ek bellek</th>
      <th>Kararlı mı?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bubble Sort</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(n^2)$</td>
      <td style="text-align: right">$O(n^2)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Insertion Sort</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(n^2)$</td>
      <td style="text-align: right">$O(n^2)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Merge Sort</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n)$</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Quick Sort</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n^2)$</td>
      <td style="text-align: right">$O(\log n)$</td>
      <td>Genellikle hayır</td>
    </tr>
    <tr>
      <td>Heap Sort</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(n\log n)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Hayır</td>
    </tr>
  </tbody>
</table>

<p>Kararlılık, eşit anahtara sahip elemanların başlangıçtaki sırasının korunmasıdır. Örneğin çalışanları önce ada, sonra departmana göre sıralıyorsanız kararlı algoritma önceki düzeni kaybetmez.</p>

<h2 id="algoritmalar-içeride-ne-yapıyor">Algoritmalar içeride ne yapıyor?</h2>

<p><strong>Bubble Sort</strong>, komşu elemanları karşılaştırır ve yanlış sıradaysa yer değiştirir. Büyük değerler köpük gibi sona çıkar. Dizi zaten sıralıysa bir <code class="language-plaintext highlighter-rouge">swapped</code> bayrağı sayesinde erkenden durabilir.</p>

<p><strong>Insertion Sort</strong>, her elemanı soldaki sıralı bölge içinde uygun konuma yerleştirir. Küçük veya neredeyse sıralı dizilerde az sayıda kaydırma yaptığı için teorik olarak daha güçlü görünen algoritmaları geçebilir.</p>

<p><strong>Merge Sort</strong>, diziyi tek elemanlı parçalara kadar böler ve parçaları sıralı biçimde birleştirir. Tahmin edilebilir performansı güçlüdür; ancak yardımcı dizi nedeniyle bellek tüketir.</p>

<p><strong>Quick Sort</strong>, bir pivot seçerek küçük değerleri sola, büyükleri sağa taşır. Pivot dengeli bölme yaparsa hızlıdır. Sürekli en küçük ya da en büyük elemanın seçilmesi ise bölümleri $0$ ve $n-1$ boyutlarına ayırarak $O(n^2)$ sonucunu doğurur.</p>

<p>Aşağıdaki kod, rastgele pivot kullanarak bu riski azaltır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">random</span>

<span class="k">def</span> <span class="nf">quick_sort</span><span class="p">(</span><span class="n">values</span><span class="p">):</span>
    <span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">values</span>

    <span class="n">pivot</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">choice</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
    <span class="n">small</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">pivot</span><span class="p">]</span>
    <span class="n">equal</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="n">pivot</span><span class="p">]</span>
    <span class="n">large</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="n">pivot</span><span class="p">]</span>

    <span class="k">return</span> <span class="nf">quick_sort</span><span class="p">(</span><span class="n">small</span><span class="p">)</span> <span class="o">+</span> <span class="n">equal</span> <span class="o">+</span> <span class="nf">quick_sort</span><span class="p">(</span><span class="n">large</span><span class="p">)</span>
</code></pre></div></div>

<p>Kod okunaklıdır ve rastgele pivot kötü durum olasılığını düşürür. Bununla birlikte yeni listeler oluşturduğu için klasik yerinde Quick Sort uygulamasından daha fazla bellek kullanır.</p>

<h2 id="optimizasyon-sorularına-yaklaşım">Optimizasyon sorularına yaklaşım</h2>

<p><strong>Soru 1: Bir milyon rastgele eleman ve sınırlı bellek varsa ne seçilir?</strong><br />
Merge Sort’un $O(n)$ ek belleği sorun olabilir. Heap Sort, $O(1)$ yardımcı bellek ve garantili $O(n\log n)$ süresiyle güvenli seçimdir. Pratikte iyi uygulanmış yerinde Quick Sort da önbellek dostu yapısıyla daha hızlı olabilir.</p>

<p><strong>Soru 2: Dizi yüzde 95 sıralıysa?</strong><br />
Insertion Sort değerlendirilmelidir. Çalışma süresi terslik sayısıyla ilişkilidir: $O(n+k)$. Buradaki $k$, yanlış sıradaki eleman çiftlerinin sayısıdır. $k$ küçükse algoritma doğrusal zamana yaklaşır.</p>

<p><strong>Soru 3: Eşit kayıtların sırası korunmalıysa?</strong><br />
Kararlı Merge Sort uygundur. Quick Sort seçilecekse kararlılığı ayrıca sağlamak gerekir; bu da bellek ve uygulama karmaşıklığı getirir.</p>

<p>Sonuç olarak “en hızlı sıralama algoritması” diye evrensel bir şampiyon yoktur. Girdi boyutu, mevcut düzen, bellek sınırı, kararlılık ihtiyacı ve en kötü durum garantisi birlikte değerlendirilmelidir. İyi optimizasyon, yalnızca Big-O seçmek değil, verinin davranışını tanımaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="sıralama algoritmaları" /><category term="algoritma analizi" /><category term="performans optimizasyonu" /><summary type="html"><![CDATA[Bir veri kümesini sıralamak, programlamanın “çorapları renklerine göre ayırma” problemidir: sonuç basit görünür, fakat doğru yöntem seçilmezse işlem gereksiz yere uzar. Bubble Sort, Merge Sort, Quick Sort ve Heap Sort aynı çıktıyı üretse de bunu yaparken farklı miktarda zaman, bellek ve karşılaştırma harcar. Optimizasyon sorularını çözebilmek için algoritmaların yalnızca karmaşıklıklarını ezberlemek değil, içeride nasıl çalıştıklarını anlamak gerekir.]]></summary></entry><entry><title type="html">tsconfig.json Rehberi: TypeScript Derleyicisini Baştan Sona Yapılandırmak</title><link href="https://sonsuzus.github.io/posts/tsconfigjson-rehberi-typescript-derleyicisini-bastan-sona-yapilandirmak/" rel="alternate" type="text/html" title="tsconfig.json Rehberi: TypeScript Derleyicisini Baştan Sona Yapılandırmak" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/tsconfigjson-rehberi-typescript-derleyicisini-bastan-sona-yapilandirmak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/tsconfigjson-rehberi-typescript-derleyicisini-bastan-sona-yapilandirmak/"><![CDATA[<p>TypeScript kodu yazmak işin yalnızca yarısıdır; diğer yarısı, bu kodun hangi JavaScript sürümüne, hangi modül sistemine ve ne kadar katı kurallarla dönüştürüleceğini belirlemektir. Projenin kontrol paneli sayılan <code class="language-plaintext highlighter-rouge">tsconfig.json</code>, derleyiciye adeta “Bu kodu nereye götürüyoruz ve yolda hangi kurallara uyuyoruz?” sorularının cevabını verir.</p>

<p>``</p>

<h2 id="derleme-ve-transpilation-mantığı">Derleme ve transpilation mantığı</h2>

<p>TypeScript derleyicisi <code class="language-plaintext highlighter-rouge">tsc</code>, <code class="language-plaintext highlighter-rouge">.ts</code> ve <code class="language-plaintext highlighter-rouge">.tsx</code> dosyalarını inceler, tip hatalarını raporlar ve gerektiğinde çalıştırılabilir JavaScript üretir. Bu işlem çoğunlukla <strong>transpilation</strong> olarak adlandırılır. Çünkü kaynak ve hedef diller benzer soyutlama seviyelerindedir.</p>

<p>Basitleştirilmiş süreç şöyle gösterilebilir:</p>

\[TypeScript + Derleyici\ Ayarları \longrightarrow JavaScript + Tip\ Kontrolü\]

<p>Burada önemli bir ayrım vardır: TypeScript tipleri çalışma zamanında JavaScript içinde yaşamaz. Örneğin <code class="language-plaintext highlighter-rouge">number</code> veya <code class="language-plaintext highlighter-rouge">User</code> gibi tip tanımları çıktı oluşturulurken silinir. Dolayısıyla TypeScript, çalışma zamanı doğrulayıcısı değil, geliştirme zamanında çalışan bir güvenlik ağıdır.</p>

<h2 id="temel-tsconfigjson-yapısı">Temel tsconfig.json yapısı</h2>

<p>Orta ölçekli bir Node.js projesi için başlangıç yapılandırması şöyle olabilir:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"compilerOptions"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"target"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ES2022"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"module"</span><span class="p">:</span><span class="w"> </span><span class="s2">"NodeNext"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"moduleResolution"</span><span class="p">:</span><span class="w"> </span><span class="s2">"NodeNext"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"rootDir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"src"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"outDir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"dist"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"strict"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
    </span><span class="nl">"esModuleInterop"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
    </span><span class="nl">"sourceMap"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
    </span><span class="nl">"declaration"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
    </span><span class="nl">"skipLibCheck"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"include"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"src/**/*.ts"</span><span class="p">],</span><span class="w">
  </span><span class="nl">"exclude"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"node_modules"</span><span class="p">,</span><span class="w"> </span><span class="s2">"dist"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">rootDir</code>, kaynak kodun bulunduğu dizini; <code class="language-plaintext highlighter-rouge">outDir</code> ise üretilen JavaScript dosyalarının gideceği dizini belirtir. <code class="language-plaintext highlighter-rouge">include</code> derlemeye katılacak, <code class="language-plaintext highlighter-rouge">exclude</code> göz ardı edilecek dosyaları tanımlar. Böylece derleyici yanlışlıkla <code class="language-plaintext highlighter-rouge">dist</code> klasörünü tekrar derleyip dijital bir matruşka bebeğe dönüşmez.</p>

<h2 id="target-module-ve-moduleresolution">target, module ve moduleResolution</h2>

<p>Bu üç ayar sıkça karıştırılır fakat farklı sorumluluklara sahiptir:</p>

<table>
  <thead>
    <tr>
      <th>Ayar</th>
      <th>Görevi</th>
      <th>Örnek değerler</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">target</code></td>
      <td>Üretilecek JavaScript sürümünü belirler</td>
      <td><code class="language-plaintext highlighter-rouge">ES2018</code>, <code class="language-plaintext highlighter-rouge">ES2022</code>, <code class="language-plaintext highlighter-rouge">ESNext</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">module</code></td>
      <td>Çıktının modül biçimini seçer</td>
      <td><code class="language-plaintext highlighter-rouge">CommonJS</code>, <code class="language-plaintext highlighter-rouge">ESNext</code>, <code class="language-plaintext highlighter-rouge">NodeNext</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">moduleResolution</code></td>
      <td>Import yollarının nasıl çözüleceğini belirler</td>
      <td><code class="language-plaintext highlighter-rouge">Node</code>, <code class="language-plaintext highlighter-rouge">NodeNext</code>, <code class="language-plaintext highlighter-rouge">Bundler</code></td>
    </tr>
  </tbody>
</table>

<p>Eski tarayıcıları desteklemek daha düşük bir <code class="language-plaintext highlighter-rouge">target</code> gerektirebilir. Ancak düşük hedef, daha fazla dönüşüm ve daha büyük çıktı anlamına gelebilir. Kabaca:</p>

\[Uyumluluk \uparrow \Rightarrow Dönüşüm\ Maliyeti \uparrow\]

<p>Modern Node.js projelerinde <code class="language-plaintext highlighter-rouge">ES2022</code> ve <code class="language-plaintext highlighter-rouge">NodeNext</code>; Vite gibi paketleyici kullanan uygulamalarda ise <code class="language-plaintext highlighter-rouge">ESNext</code> ile <code class="language-plaintext highlighter-rouge">Bundler</code> genellikle mantıklı tercihlerdir.</p>

<h2 id="strict-modu-neden-önemlidir">strict modu neden önemlidir?</h2>

<p><code class="language-plaintext highlighter-rouge">strict: true</code>, birden fazla güvenlik seçeneğini topluca etkinleştirir. Bunların arasında <code class="language-plaintext highlighter-rouge">strictNullChecks</code>, <code class="language-plaintext highlighter-rouge">noImplicitAny</code> ve <code class="language-plaintext highlighter-rouge">strictFunctionTypes</code> bulunur.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">kullaniciAdi</span><span class="p">(</span><span class="nx">ad</span><span class="p">:</span> <span class="kr">string</span> <span class="o">|</span> <span class="kc">null</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="nx">ad</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">Misafir</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">ad</span><span class="p">.</span><span class="nf">toUpperCase</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">strictNullChecks</code> açıkken <code class="language-plaintext highlighter-rouge">null</code>, sıradan bir <code class="language-plaintext highlighter-rouge">string</code> gibi kullanılamaz. Kod önce olası boş değeri kontrol eder. Bu yaklaşım biraz daha fazla kod yazdırsa da üretimdeki “undefined nereden geldi?” dedektifliğini ciddi biçimde azaltır.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">strict: false</code></td>
      <td>Hızlı başlangıç</td>
      <td>Hatalar çalışma zamanına sızabilir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">strict: true</code></td>
      <td>Güçlü tip güvenliği</td>
      <td>Eski projelerde çok hata gösterebilir</td>
    </tr>
    <tr>
      <td>Kademeli geçiş</td>
      <td>Kontrollü iyileştirme</td>
      <td>Geçici ayar karmaşası yaratabilir</td>
    </tr>
  </tbody>
</table>

<h2 id="mimariye-göre-ek-ayarlar">Mimariye göre ek ayarlar</h2>

<p>Kütüphane geliştiriyorsanız <code class="language-plaintext highlighter-rouge">declaration: true</code>, tüketiciler için <code class="language-plaintext highlighter-rouge">.d.ts</code> dosyaları üretir. Yalnızca tip kontrolü yapıp çıktıyı Babel, SWC veya Vite’a bırakacaksanız <code class="language-plaintext highlighter-rouge">noEmit: true</code> kullanılabilir. <code class="language-plaintext highlighter-rouge">sourceMap: true</code> ise çalışan JavaScript hatalarını özgün TypeScript satırlarıyla eşleştirerek hata ayıklamayı kolaylaştırır.</p>

<p>Paylaşılan yapılarda temel ayarları ayrı bir dosyada tutmak da mümkündür:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"extends"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./tsconfig.base.json"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"compilerOptions"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"outDir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"dist/server"</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"include"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"src/server/**/*.ts"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Sonuç olarak iyi bir <code class="language-plaintext highlighter-rouge">tsconfig.json</code>, rastgele seçenekler koleksiyonu değil, projenin çalışma ortamını ve kalite beklentisini belgeleyen mimari bir sözleşmedir. Ayarları kopyalayıp geçmek yerine hedef platformu, modül sistemini ve dağıtım yöntemini düşünmek; daha anlaşılır, güvenli ve taşınabilir projeler üretir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="TypeScript" /><category term="tsconfig" /><category term="JavaScript" /><summary type="html"><![CDATA[TypeScript kodu yazmak işin yalnızca yarısıdır; diğer yarısı, bu kodun hangi JavaScript sürümüne, hangi modül sistemine ve ne kadar katı kurallarla dönüştürüleceğini belirlemektir. Projenin kontrol paneli sayılan tsconfig.json, derleyiciye adeta “Bu kodu nereye götürüyoruz ve yolda hangi kurallara uyuyoruz?” sorularının cevabını verir.]]></summary></entry><entry><title type="html">TypeScript Tip Korumaları: typeof, instanceof ve in ile Güvenli Daraltma</title><link href="https://sonsuzus.github.io/posts/typescript-tip-korumalari-typeof-instanceof-ve-in-ile-guvenli-daraltma/" rel="alternate" type="text/html" title="TypeScript Tip Korumaları: typeof, instanceof ve in ile Güvenli Daraltma" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-08-05T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/typescript-tip-korumalari-typeof-instanceof-ve-in-ile-guvenli-daraltma</id><content type="html" xml:base="https://sonsuzus.github.io/posts/typescript-tip-korumalari-typeof-instanceof-ve-in-ile-guvenli-daraltma/"><![CDATA[<p>TypeScript’te bir değişken bazen birden fazla olası tipe sahip olabilir. Böyle durumlarda derleyici, hangi tipe özgü işlemin güvenli olduğunu kendiliğinden bilemez. Tip korumaları (type guards), programın akışındaki kontrolleri kullanarak olası tip kümesini küçültür. Bu işleme <strong>tip daraltma (narrowing)</strong> denir. Böylece kod hem güvenli hem de gereksiz tür dönüşümlerinden uzak hâle gelir.
``</p>
<h2 id="daraltmanın-temel-mantığı">Daraltmanın temel mantığı</h2>

<p>Bir değişkenin tipi <code class="language-plaintext highlighter-rouge">string | number</code> ise onu matematiksel olarak bir birleşim kümesi gibi düşünebiliriz:</p>

\[T = \{string, number\}\]

<p><code class="language-plaintext highlighter-rouge">typeof value === "string"</code> kontrolünün doğru olduğu dalda TypeScript, olası tipleri filtreler:</p>

\[T' = T \cap \{string\} = \{string\}\]

<p>Başka bir ifadeyle çalışma zamanındaki bir koşul, derleme zamanındaki tip bilgisini daha kesin hâle getirir. Koşulun diğer dalında ise geriye <code class="language-plaintext highlighter-rouge">number</code> kalır.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">biçimlendir</span><span class="p">(</span><span class="nx">value</span><span class="p">:</span> <span class="kr">string</span> <span class="o">|</span> <span class="kr">number</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="k">typeof</span> <span class="nx">value</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// value burada string olarak daraltılır.</span>
    <span class="k">return</span> <span class="nx">value</span><span class="p">.</span><span class="nf">trim</span><span class="p">().</span><span class="nf">toUpperCase</span><span class="p">();</span>
  <span class="p">}</span>

  <span class="c1">// String seçeneği elendiği için value artık number'dır.</span>
  <span class="k">return</span> <span class="nx">value</span><span class="p">.</span><span class="nf">toFixed</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu yaklaşım, riskli <code class="language-plaintext highlighter-rouge">as string</code> ifadeleriyle derleyiciyi susturmak yerine gerçekten doğrulanmış bilgi üretir.</p>

<h2 id="üç-temel-koruma-yöntemi">Üç temel koruma yöntemi</h2>

<table>
  <thead>
    <tr>
      <th>Operatör</th>
      <th>En uygun kullanım</th>
      <th>Örnek kontrol</th>
      <th>Daraltılan yapı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">typeof</code></td>
      <td>İlkel değerler</td>
      <td><code class="language-plaintext highlighter-rouge">typeof x === "number"</code></td>
      <td><code class="language-plaintext highlighter-rouge">string</code>, <code class="language-plaintext highlighter-rouge">number</code>, <code class="language-plaintext highlighter-rouge">boolean</code> gibi tipler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">instanceof</code></td>
      <td>Sınıf örnekleri</td>
      <td><code class="language-plaintext highlighter-rouge">x instanceof Date</code></td>
      <td>Sınıf ve kalıtım zinciri</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">in</code></td>
      <td>Nesne özellikleri</td>
      <td><code class="language-plaintext highlighter-rouge">"speed" in vehicle</code></td>
      <td>Belirli özelliği taşıyan nesne tipi</td>
    </tr>
  </tbody>
</table>

<h3 id="typeof-i̇lkel-tiplerin-bekçisi"><code class="language-plaintext highlighter-rouge">typeof</code>: İlkel tiplerin bekçisi</h3>

<p><code class="language-plaintext highlighter-rouge">typeof</code>, özellikle union tipindeki ilkel değerlerde kullanışlıdır. Ancak JavaScript’in tarihî tuzaklarından biri unutulmamalıdır: <code class="language-plaintext highlighter-rouge">typeof null</code> sonucu <code class="language-plaintext highlighter-rouge">"object"</code> değeridir. Bu nedenle nesne kontrolünde ayrıca <code class="language-plaintext highlighter-rouge">value !== null</code> koşulu gerekir.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">uzunluk</span><span class="p">(</span><span class="nx">value</span><span class="p">:</span> <span class="kr">string</span> <span class="o">|</span> <span class="kr">string</span><span class="p">[]</span> <span class="o">|</span> <span class="kc">null</span><span class="p">):</span> <span class="kr">number</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="nx">value</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>

  <span class="k">if </span><span class="p">(</span><span class="k">typeof</span> <span class="nx">value</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">value</span><span class="p">.</span><span class="nf">trim</span><span class="p">().</span><span class="nx">length</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="c1">// Burada value string[] tipindedir.</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="instanceof-sınıfları-ayırt-etmek"><code class="language-plaintext highlighter-rouge">instanceof</code>: Sınıfları ayırt etmek</h3>

<p><code class="language-plaintext highlighter-rouge">instanceof</code>, bir nesnenin belirli bir constructor’ın prototip zincirinden gelip gelmediğini çalışma zamanında sınar. Bu nedenle interface’lerle doğrudan kullanılamaz; interface’ler JavaScript çıktısında bulunmaz.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Kedi</span> <span class="p">{</span>
  <span class="nf">miyavla</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">Miyav!</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Köpek</span> <span class="p">{</span>
  <span class="nf">havla</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">Hav hav!</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nf">konuştur</span><span class="p">(</span><span class="nx">hayvan</span><span class="p">:</span> <span class="nx">Kedi</span> <span class="o">|</span> <span class="nx">Köpek</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="nx">hayvan</span> <span class="k">instanceof</span> <span class="nx">Kedi</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">hayvan</span><span class="p">.</span><span class="nf">miyavla</span><span class="p">();</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">hayvan</span><span class="p">.</span><span class="nf">havla</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada TypeScript, ilk dalda <code class="language-plaintext highlighter-rouge">Kedi</code>, kalan dalda ise <code class="language-plaintext highlighter-rouge">Köpek</code> işlemlerine izin verir. Hayvanat bahçesi küçük, tip güvenliği büyüktür!</p>

<h3 id="in-özelliğe-bakarak-seçim-yapmak"><code class="language-plaintext highlighter-rouge">in</code>: Özelliğe bakarak seçim yapmak</h3>

<p><code class="language-plaintext highlighter-rouge">in</code> operatörü, bir özelliğin nesnede veya prototip zincirinde bulunup bulunmadığını kontrol eder. Özellikle farklı alanlara sahip nesne birleşimlerinde okunaklıdır.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Araba</span> <span class="o">=</span> <span class="p">{</span> <span class="na">marka</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">sür</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="p">};</span>
<span class="kd">type</span> <span class="nx">Tekne</span> <span class="o">=</span> <span class="p">{</span> <span class="na">ad</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">yüz</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="p">};</span>

<span class="kd">function</span> <span class="nf">hareketEt</span><span class="p">(</span><span class="nx">araç</span><span class="p">:</span> <span class="nx">Araba</span> <span class="o">|</span> <span class="nx">Tekne</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="dl">"</span><span class="s2">sür</span><span class="dl">"</span> <span class="k">in</span> <span class="nx">araç</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">araç</span><span class="p">.</span><span class="nf">sür</span><span class="p">();</span> <span class="c1">// araç artık Araba</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">araç</span><span class="p">.</span><span class="nf">yüz</span><span class="p">();</span> <span class="c1">// araç artık Tekne</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="özel-tip-koruması-yazmak">Özel tip koruması yazmak</h2>

<p>Karmaşık doğrulamaları tekrar kullanmak için dönüş tipi <code class="language-plaintext highlighter-rouge">değer is Tip</code> biçiminde olan fonksiyonlar yazılabilir:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Kullanıcı</span> <span class="o">=</span> <span class="p">{</span> <span class="na">id</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span> <span class="nl">ad</span><span class="p">:</span> <span class="kr">string</span> <span class="p">};</span>

<span class="kd">function</span> <span class="nf">kullanıcıMı</span><span class="p">(</span><span class="nx">value</span><span class="p">:</span> <span class="nx">unknown</span><span class="p">):</span> <span class="nx">value</span> <span class="k">is</span> <span class="nx">Kullanıcı</span> <span class="p">{</span>
  <span class="k">return </span><span class="p">(</span>
    <span class="k">typeof</span> <span class="nx">value</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">object</span><span class="dl">"</span> <span class="o">&amp;&amp;</span>
    <span class="nx">value</span> <span class="o">!==</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span>
    <span class="dl">"</span><span class="s2">id</span><span class="dl">"</span> <span class="k">in</span> <span class="nx">value</span> <span class="o">&amp;&amp;</span>
    <span class="dl">"</span><span class="s2">ad</span><span class="dl">"</span> <span class="k">in</span> <span class="nx">value</span> <span class="o">&amp;&amp;</span>
    <span class="k">typeof</span> <span class="nx">value</span><span class="p">.</span><span class="nx">id</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">number</span><span class="dl">"</span> <span class="o">&amp;&amp;</span>
    <span class="k">typeof</span> <span class="nx">value</span><span class="p">.</span><span class="nx">ad</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span>
  <span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu fonksiyon <code class="language-plaintext highlighter-rouge">true</code> döndürdüğünde çağıran kapsamda değer <code class="language-plaintext highlighter-rouge">Kullanıcı</code> olarak daraltılır. Yine de TypeScript bu söze güvenir; hatalı yazılmış bir koruma sahte güvenlik oluşturabilir. Sonuç olarak doğru koruma, “Ben bunun tipini biliyorum” demek değil, bunu çalışma zamanında kanıtlamaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="TypeScript" /><category term="Type Guards" /><category term="Narrowing" /><summary type="html"><![CDATA[TypeScript’te bir değişken bazen birden fazla olası tipe sahip olabilir. Böyle durumlarda derleyici, hangi tipe özgü işlemin güvenli olduğunu kendiliğinden bilemez. Tip korumaları (type guards), programın akışındaki kontrolleri kullanarak olası tip kümesini küçültür. Bu işleme tip daraltma (narrowing) denir. Böylece kod hem güvenli hem de gereksiz tür dönüşümlerinden uzak hâle gelir.]]></summary></entry></feed>