<?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://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-14T18:05:48+00:00</updated><id>https://program.sonsuz.us/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">2-3 Arama Ağaçları ve Kırmızı-Siyah Ağaçlarla Gizli Akrabalığı</title><link href="https://program.sonsuz.us/posts/2-3-arama-agaclari-ve-kirmizi-siyah-agaclarla-gizli-akrabaligi/" rel="alternate" type="text/html" title="2-3 Arama Ağaçları ve Kırmızı-Siyah Ağaçlarla Gizli Akrabalığı" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/2-3-arama-agaclari-ve-kirmizi-siyah-agaclarla-gizli-akrabaligi</id><content type="html" xml:base="https://program.sonsuz.us/posts/2-3-arama-agaclari-ve-kirmizi-siyah-agaclarla-gizli-akrabaligi/"><![CDATA[<p>İkili arama ağaçları hızlı arama sunar; fakat anahtarlar sıralı geldiğinde ağaç bir çubuk gibi uzayabilir. 2-3 arama ağaçları bu sorunu, her düğümde bir yerine birden fazla anahtar saklayarak çözer. Daha da ilginci, kırmızı-siyah ağaçlar bu çok anahtarlı yapının ikili ağaç kılığına girmiş hâli olarak yorumlanabilir.</p>

<p><img src="/img/2-3-arama-17.svg" alt="2-3-arama-17" /></p>

<p>``</p>

<h2 id="2-3-ağacı-nedir">2-3 ağacı nedir?</h2>

<p>Bir 2-3 ağacındaki iç düğüm iki biçimden birine sahiptir:</p>

<ul>
  <li><strong>2-düğüm:</strong> Bir anahtar ve iki çocuk taşır.</li>
  <li><strong>3-düğüm:</strong> İki sıralı anahtar ve üç çocuk taşır.</li>
</ul>

<p>Bir 3-düğümde anahtarlar $a &lt; b$ ise sol alt ağaçtaki değerler $a$’dan küçük, ortadakiler $a$ ile $b$ arasında, sağdakiler ise $b$’den büyüktür. Böylece ikili arama ağacının sıralama mantığı korunurken tek seviyede daha fazla bilgi tutulur.</p>

<p>Asıl denge garantisi şu değişmezden gelir: <strong>Bütün yapraklar aynı derinliktedir.</strong> Ağacın yüksekliği $h$ ve anahtar sayısı $n$ olduğunda en seyrek durumda her düğüm iki çocukludur:</p>

\[2^h - 1 \leq n\]

<p>En yoğun durumda ise dallanma üçe yaklaşır. Dolayısıyla yükseklik kabaca</p>

\[\log_3(n) \leq h \leq \log_2(n+1)\]

<p>aralığındadır. Arama, ekleme ve silme işlemleri bu nedenle en kötü durumda $O(\log n)$ sürer.</p>

<h2 id="arama-nasıl-ilerler">Arama nasıl ilerler?</h2>

<p>Her düğümde bir veya iki anahtar karşılaştırılır. Aranan değer küçükse sola, iki anahtarın arasındaysa ortaya, büyükse sağa gidilir. Yani bir seviyede daha çok karşılaştırma yapılabilir; buna karşılık ağaç genellikle daha kısadır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>İkili arama ağacı</th>
      <th>2-3 ağacı</th>
      <th>Kırmızı-siyah ağaç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Düğümdeki anahtar</td>
      <td>1</td>
      <td>1 veya 2</td>
      <td>1</td>
    </tr>
    <tr>
      <td>Çocuk sayısı</td>
      <td>En fazla 2</td>
      <td>2 veya 3</td>
      <td>En fazla 2</td>
    </tr>
    <tr>
      <td>Denge garantisi</td>
      <td>Yok</td>
      <td>Tam yükseklik dengesi</td>
      <td>Siyah yükseklik dengesi</td>
    </tr>
    <tr>
      <td>En kötü arama</td>
      <td>$O(n)$</td>
      <td>$O(\log n)$</td>
      <td>$O(\log n)$</td>
    </tr>
    <tr>
      <td>Uygulama yaklaşımı</td>
      <td>Basit</td>
      <td>Çok yollu</td>
      <td>Döndürme ve renk değiştirme</td>
    </tr>
  </tbody>
</table>

<h2 id="ekleme-ve-düğüm-bölme">Ekleme ve düğüm bölme</h2>

<p>Yeni anahtar uygun yaprağa eklenir. Yaprak bir 2-düğümse anahtarlar sıralanır ve düğüm 3-düğüme dönüşür. Zaten iki anahtarı varsa geçici olarak üç anahtarlı bir taşma oluşur. Ortadaki anahtar ebeveyne gönderilir; küçük ve büyük anahtarlar iki ayrı düğüme bölünür. Ebeveyn de taşarsa işlem köke kadar devam eder. Kökün bölünmesi ağacın yüksekliğini yalnızca bir artırır.</p>

<p>Aşağıdaki Python kodu bu bölmenin özünü gösterir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">split_keys</span><span class="p">(</span><span class="n">keys</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">Üç sıralı anahtarı iki düğüm ve bir terfi anahtarına ayırır.</span><span class="sh">"""</span>
    <span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">3</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">Bölme için tam olarak üç anahtar gerekir</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">left</span> <span class="o">=</span> <span class="p">[</span><span class="n">keys</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
    <span class="n">promoted</span> <span class="o">=</span> <span class="n">keys</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
    <span class="n">right</span> <span class="o">=</span> <span class="p">[</span><span class="n">keys</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
    <span class="k">return</span> <span class="n">left</span><span class="p">,</span> <span class="n">promoted</span><span class="p">,</span> <span class="n">right</span>

<span class="n">keys</span> <span class="o">=</span> <span class="nf">sorted</span><span class="p">([</span><span class="mi">40</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">25</span><span class="p">])</span>
<span class="n">left</span><span class="p">,</span> <span class="n">promoted</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="nf">split_keys</span><span class="p">(</span><span class="n">keys</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">promoted</span><span class="p">,</span> <span class="n">right</span><span class="p">)</span>  <span class="c1"># [10] 25 [40]
</span></code></pre></div></div>

<p>Gerçek uygulamada çocuk işaretçileri de uygun yeni düğümlere dağıtılır. Kodun önemli fikri, ortanca anahtarın yukarı çıkarak sıralamayı ve eşit yaprak derinliğini korumasıdır.</p>

<h2 id="kırmızı-siyah-bağlantısı">Kırmızı-siyah bağlantısı</h2>

<p>Bir 2-3 ağacını sıradan ikili bağlantılarla temsil etmek için 3-düğümdeki iki anahtar birbirine <strong>kırmızı bağlantıyla</strong> bağlanabilir. Tek başına duran 2-düğüm ise siyah bir düğüm olur:</p>

<ul>
  <li>Siyah düğüm, bir 2-düğümü temsil eder.</li>
  <li>Siyah düğüm ile kırmızı çocuğu birlikte, bir 3-düğümü temsil eder.</li>
  <li>Kökten yapraklara eşit siyah düğüm sayısı, 2-3 ağacındaki eşit derinliğe karşılık gelir.</li>
</ul>

<p>Özellikle sola yatık kırmızı-siyah ağaçlarda kırmızı bağlantı yalnızca sola eğilir. Ekleme sırasında yapılan sola döndürme, sağa döndürme ve renk değiştirme işlemleri; 2-3 ağacındaki düğüm birleştirme, bölme ve anahtar terfisinin ikili ağaç üzerindeki karşılıklarıdır.</p>

<p>Sonuç olarak 2-3 ağaçları dengeyi kavramsal olarak zarif biçimde garanti ederken kırmızı-siyah ağaçlar aynı fikri tek anahtarlı düğümlerle, pratik programlama ortamlarına daha uygun şekilde uygular. Renkler süs değil; görünmez 3-düğümleri işaretleyen küçük trafik lambalarıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="2-3 ağaçları" /><category term="kırmızı-siyah ağaçlar" /><category term="veri yapıları" /><category term="algoritmalar" /><category term="dengeli ağaçlar" /><summary type="html"><![CDATA[İkili arama ağaçları hızlı arama sunar; fakat anahtarlar sıralı geldiğinde ağaç bir çubuk gibi uzayabilir. 2-3 arama ağaçları bu sorunu, her düğümde bir yerine birden fazla anahtar saklayarak çözer. Daha da ilginci, kırmızı-siyah ağaçlar bu çok anahtarlı yapının ikili ağaç kılığına girmiş hâli olarak yorumlanabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/2-3-arama-17.png" /><media:content medium="image" url="https://program.sonsuz.us/img/2-3-arama-17.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">A* Arama Algoritması: Sezgilerle En Kısa Yolu Bulmak</title><link href="https://program.sonsuz.us/posts/a-arama-algoritmasi-sezgilerle-en-kisa-yolu-bulmak/" rel="alternate" type="text/html" title="A* Arama Algoritması: Sezgilerle En Kısa Yolu Bulmak" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/a-arama-algoritmasi-sezgilerle-en-kisa-yolu-bulmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/a-arama-algoritmasi-sezgilerle-en-kisa-yolu-bulmak/"><![CDATA[<p>Bir labirentte çıkışı aradığınızı düşünün. Dijkstra algoritması, hedefin hangi yönde olduğunu önemsemeden çevresindeki yolları sabırla inceler. A* ise aynı işi yaparken hedefe doğru ne kadar yaklaştığını tahmin eden bir pusula kullanır. Bu sezgisel yaklaşım, doğru koşullarda en kısa yolu korurken gereksiz düğümleri ziyaret etmeyi azaltabilir.</p>

<p>``</p>

<h2 id="a-algoritmasının-temel-fikri">A* algoritmasının temel fikri</h2>

<p>A*, ağırlıklı bir graf üzerinde başlangıç düğümünden hedef düğüme giden en düşük maliyetli yolu arar. Her düğüm için üç önemli değer kullanır:</p>

\[f(n) = g(n) + h(n)\]

<ul>
  <li>$g(n)$: Başlangıçtan $n$ düğümüne kadar ödenen gerçek maliyettir.</li>
  <li>$h(n)$: $n$ düğümünden hedefe kalan maliyetin tahminidir.</li>
  <li>$f(n)$: Düğüm üzerinden geçen yolun tahmini toplam maliyetidir.</li>
</ul>

<p>Algoritma, sıradaki adım olarak $f(n)$ değeri en küçük olan düğümü seçer. Başka bir deyişle geçmişte ödediği maliyet ile gelecekte ödeyeceğini düşündüğü maliyeti birlikte değerlendirir.</p>

<table>
  <thead>
    <tr>
      <th>Algoritma</th>
      <th style="text-align: right">Kullanılan değer</th>
      <th>Hedef bilgisi</th>
      <th>Genel davranış</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dijkstra</td>
      <td style="text-align: right">$g(n)$</td>
      <td>Kullanmaz</td>
      <td>Her yöne dengeli yayılır</td>
    </tr>
    <tr>
      <td>Greedy Best-First</td>
      <td style="text-align: right">$h(n)$</td>
      <td>Kullanır</td>
      <td>Hedefe koşar, en kısa yolu garanti etmeyebilir</td>
    </tr>
    <tr>
      <td>A*</td>
      <td style="text-align: right">$g(n)+h(n)$</td>
      <td>Kullanır</td>
      <td>Maliyet ile yön tahminini dengeler</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/a-arama-algoritmasi-25.svg" alt="a-arama-algoritmasi-25" /></p>

<p>Aslında $h(n)=0$ seçilirse A<em>, Dijkstra algoritmasına dönüşür. Dolayısıyla A</em> için Dijkstra’nın hedef bilgisiyle güçlendirilmiş hâli denebilir.</p>

<h2 id="sezgisel-fonksiyon-nasıl-seçilir">Sezgisel fonksiyon nasıl seçilir?</h2>

<p>Kareli ve dört yönde hareket edilen bir haritada Manhattan uzaklığı kullanılabilir:</p>

\[h(n)=\vert x_n-x_h\vert +\vert y_n-y_h\vert\]

<p>Çapraz hareket mümkünse Öklid uzaklığı daha uygun olabilir. A*‘ın en kısa yolu garanti etmesi için sezgisel fonksiyonun gerçek kalan maliyeti aşmaması gerekir. Bu özelliğe <strong>kabul edilebilirlik</strong> denir. Ayrıca tutarlı bir sezgi için her kenarda şu koşul sağlanır:</p>

\[h(n) \leq c(n,m)+h(m)\]

<p>Tahmin çok küçükse algoritma güvenli fakat Dijkstra’ya yakın çalışır. Tahmin gereğinden büyükse daha hızlı görünebilir, ancak en kısa yol garantisi kaybolabilir.</p>

<h2 id="python-ile-a-uygulaması">Python ile A* uygulaması</h2>

<p>Aşağıdaki kod, sözlük biçiminde tanımlanmış ağırlıklı bir graf üzerinde çalışır. Öncelik kuyruğu, tahmini toplam maliyeti en düşük düğümü verimli biçimde seçer.</p>

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

<span class="k">def</span> <span class="nf">a_star</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">goal</span><span class="p">,</span> <span class="n">heuristic</span><span class="p">):</span>
    <span class="c1"># Kuyruk elemanları: (f maliyeti, düğüm)
</span>    <span class="n">open_set</span> <span class="o">=</span> <span class="p">[(</span><span class="nf">heuristic</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">goal</span><span class="p">),</span> <span class="n">start</span><span class="p">)]</span>
    <span class="n">came_from</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="n">g_score</span> <span class="o">=</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="n">visited</span> <span class="o">=</span> <span class="nf">set</span><span class="p">()</span>

    <span class="k">while</span> <span class="n">open_set</span><span class="p">:</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">current</span> <span class="o">=</span> <span class="nf">heappop</span><span class="p">(</span><span class="n">open_set</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">current</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="k">continue</span>
        <span class="k">if</span> <span class="n">current</span> <span class="o">==</span> <span class="n">goal</span><span class="p">:</span>
            <span class="n">path</span> <span class="o">=</span> <span class="p">[</span><span class="n">current</span><span class="p">]</span>
            <span class="k">while</span> <span class="n">current</span> <span class="ow">in</span> <span class="n">came_from</span><span class="p">:</span>
                <span class="n">current</span> <span class="o">=</span> <span class="n">came_from</span><span class="p">[</span><span class="n">current</span><span class="p">]</span>
                <span class="n">path</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">current</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">path</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">g_score</span><span class="p">[</span><span class="n">goal</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">current</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">neighbor</span><span class="p">,</span> <span class="n">edge_cost</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">current</span><span class="p">]:</span>
            <span class="n">tentative</span> <span class="o">=</span> <span class="n">g_score</span><span class="p">[</span><span class="n">current</span><span class="p">]</span> <span class="o">+</span> <span class="n">edge_cost</span>

            <span class="k">if</span> <span class="n">tentative</span> <span class="o">&lt;</span> <span class="n">g_score</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">neighbor</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="n">came_from</span><span class="p">[</span><span class="n">neighbor</span><span class="p">]</span> <span class="o">=</span> <span class="n">current</span>
                <span class="n">g_score</span><span class="p">[</span><span class="n">neighbor</span><span class="p">]</span> <span class="o">=</span> <span class="n">tentative</span>
                <span class="n">f_score</span> <span class="o">=</span> <span class="n">tentative</span> <span class="o">+</span> <span class="nf">heuristic</span><span class="p">(</span><span class="n">neighbor</span><span class="p">,</span> <span class="n">goal</span><span class="p">)</span>
                <span class="nf">heappush</span><span class="p">(</span><span class="n">open_set</span><span class="p">,</span> <span class="p">(</span><span class="n">f_score</span><span class="p">,</span> <span class="n">neighbor</span><span class="p">))</span>

    <span class="k">return</span> <span class="bp">None</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>
</code></pre></div></div>

<p>Örnek olarak düğümlerin koordinatlarını ve bağlantılarını tanımlayabiliriz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">graph</span> <span class="o">=</span> <span class="p">{</span>
    <span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">:</span> <span class="p">[(</span><span class="sh">"</span><span class="s">B</span><span class="sh">"</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="sh">"</span><span class="s">C</span><span class="sh">"</span><span class="p">,</span> <span class="mi">4</span><span class="p">)],</span>
    <span class="sh">"</span><span class="s">B</span><span class="sh">"</span><span class="p">:</span> <span class="p">[(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="sh">"</span><span class="s">D</span><span class="sh">"</span><span class="p">,</span> <span class="mi">3</span><span class="p">)],</span>
    <span class="sh">"</span><span class="s">C</span><span class="sh">"</span><span class="p">:</span> <span class="p">[(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="p">(</span><span class="sh">"</span><span class="s">D</span><span class="sh">"</span><span class="p">,</span> <span class="mi">1</span><span class="p">)],</span>
    <span class="sh">"</span><span class="s">D</span><span class="sh">"</span><span class="p">:</span> <span class="p">[(</span><span class="sh">"</span><span class="s">B</span><span class="sh">"</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="sh">"</span><span class="s">C</span><span class="sh">"</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="sh">"</span><span class="s">E</span><span class="sh">"</span><span class="p">,</span> <span class="mi">2</span><span class="p">)],</span>
    <span class="sh">"</span><span class="s">E</span><span class="sh">"</span><span class="p">:</span> <span class="p">[]</span>
<span class="p">}</span>

<span class="n">coords</span> <span class="o">=</span> <span class="p">{</span>
    <span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">:</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="sh">"</span><span class="s">B</span><span class="sh">"</span><span class="p">:</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="sh">"</span><span class="s">C</span><span class="sh">"</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="sh">"</span><span class="s">D</span><span class="sh">"</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="sh">"</span><span class="s">E</span><span class="sh">"</span><span class="p">:</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">def</span> <span class="nf">manhattan</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="n">x1</span><span class="p">,</span> <span class="n">y1</span> <span class="o">=</span> <span class="n">coords</span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
    <span class="n">x2</span><span class="p">,</span> <span class="n">y2</span> <span class="o">=</span> <span class="n">coords</span><span class="p">[</span><span class="n">b</span><span class="p">]</span>
    <span class="k">return</span> <span class="nf">abs</span><span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="n">x2</span><span class="p">)</span> <span class="o">+</span> <span class="nf">abs</span><span class="p">(</span><span class="n">y1</span> <span class="o">-</span> <span class="n">y2</span><span class="p">)</span>

<span class="n">path</span><span class="p">,</span> <span class="n">cost</span> <span class="o">=</span> <span class="nf">a_star</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">E</span><span class="sh">"</span><span class="p">,</span> <span class="n">manhattan</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">cost</span><span class="p">)</span>
</code></pre></div></div>

<p>Bu uygulama yolu <code class="language-plaintext highlighter-rouge">A, B, D, E</code> veya aynı maliyetli uygun bir alternatif olarak döndürebilir. A* özellikle oyun haritaları, robot navigasyonu ve rota planlama sistemlerinde güçlüdür. Yine de hız avantajı otomatik değildir: kötü bir sezgisel fonksiyon, büyük bellek tüketimi veya düzensiz graf yapısı performansı azaltabilir. İyi bir $h(n)$ seçimi ise A*‘ın gerçek süper gücüdür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="a-star" /><category term="arama-algoritmaları" /><category term="python" /><category term="yapay-zeka" /><category term="graf-teorisi" /><category term="algoritma" /><summary type="html"><![CDATA[Bir labirentte çıkışı aradığınızı düşünün. Dijkstra algoritması, hedefin hangi yönde olduğunu önemsemeden çevresindeki yolları sabırla inceler. A* ise aynı işi yaparken hedefe doğru ne kadar yaklaştığını tahmin eden bir pusula kullanır. Bu sezgisel yaklaşım, doğru koşullarda en kısa yolu korurken gereksiz düğümleri ziyaret etmeyi azaltabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/a-arama-algoritmasi-25.png" /><media:content medium="image" url="https://program.sonsuz.us/img/a-arama-algoritmasi-25.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Ağırlıklı Hızlı-Birleşme: Union-Find Ağaçlarını Dengede Tutmak</title><link href="https://program.sonsuz.us/posts/agirlikli-hizli-birlesme-union-find-agaclarini-dengede-tutmak/" rel="alternate" type="text/html" title="Ağırlıklı Hızlı-Birleşme: Union-Find Ağaçlarını Dengede Tutmak" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/agirlikli-hizli-birlesme-union-find-agaclarini-dengede-tutmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/agirlikli-hizli-birlesme-union-find-agaclarini-dengede-tutmak/"><![CDATA[<p>Union-Find, elemanların hangi gruba ait olduğunu hızlıca belirlemek ve iki grubu birleştirmek için kullanılan klasik bir veri yapısıdır. Ancak grupları düşünmeden birleştirirsek ortaya uzun, ince ve performans düşmanı ağaçlar çıkabilir. Ağırlıklı Hızlı-Birleşme (Weighted Quick-Union), küçük ağacı büyük ağacın altına bağlayarak bu sorunu oldukça zarif biçimde çözer.</p>

<p>``</p>

<h2 id="union-find-hangi-problemi-çözer">Union-Find hangi problemi çözer?</h2>

<p>Elimizde başlangıçta birbirinden bağımsız $N$ eleman bulunduğunu düşünelim. Union-Find iki temel işlemi destekler:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">find(p)</code>: <code class="language-plaintext highlighter-rouge">p</code> elemanının bağlı olduğu kümenin kökünü bulur.</li>
  <li><code class="language-plaintext highlighter-rouge">union(p, q)</code>: <code class="language-plaintext highlighter-rouge">p</code> ve <code class="language-plaintext highlighter-rouge">q</code> elemanlarının kümelerini birleştirir.</li>
</ul>

<p>Bu yapı; sosyal ağ bağlantıları, bilgisayar ağları, görüntü işleme, labirent üretimi ve Kruskal’ın minimum kapsayan ağaç algoritması gibi birçok alanda kullanılır.</p>

<p>Quick-Union yaklaşımında her eleman, ebeveyninin indeksini saklar. Bir kökte <code class="language-plaintext highlighter-rouge">parent[i] == i</code> olur. <code class="language-plaintext highlighter-rouge">find</code>, ebeveyn bağlantılarını köke ulaşıncaya kadar takip eder. Ne var ki birleşimler kötü sırayla yapılırsa ağaç bir zincire dönüşebilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Birleştirme stratejisi</th>
      <th style="text-align: right">Olası ağaç yüksekliği</th>
      <th style="text-align: right">En kötü <code class="language-plaintext highlighter-rouge">find</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Quick-Union</td>
      <td>Bir kökü diğerine rastgele bağlar</td>
      <td style="text-align: right">$N-1$</td>
      <td style="text-align: right">$O(N)$</td>
    </tr>
    <tr>
      <td>Weighted Quick-Union</td>
      <td>Küçük ağacı büyük ağaca bağlar</td>
      <td style="text-align: right">$log_2 N$</td>
      <td style="text-align: right">$O(log N)$</td>
    </tr>
    <tr>
      <td>Yol sıkıştırmalı ağırlıklı sürüm</td>
      <td>Düğümleri köke yaklaştırır</td>
      <td style="text-align: right">Çok düşük</td>
      <td style="text-align: right">Yaklaşık $O(α(N))$</td>
    </tr>
  </tbody>
</table>

<p>Buradaki $α(N)$, ters Ackermann fonksiyonudur ve pratik veri boyutlarında neredeyse sabit kabul edilir.</p>

<h2 id="ağırlık-neden-işe-yarar">Ağırlık neden işe yarar?</h2>

<p>Her kök için ağacındaki eleman sayısını tutan bir <code class="language-plaintext highlighter-rouge">size</code> dizisi kullanılır. İki küme birleştirilirken küçük ağacın kökü, büyük ağacın köküne bağlanır. Böylece büyük ağaçtaki düğümlerin derinliği hiç değişmez; yalnızca küçük ağaçtaki düğümlerin derinliği bir artabilir.</p>

<p>Bir düğümün derinliği her arttığında, içinde bulunduğu ağacın büyüklüğü en az iki katına çıkar. Derinlik $h$ ise ağacın en az $2^h$ elemanı olmalıdır:</p>

\[2^h ≤ N \Rightarrow h ≤ log_2 N\]

<p>İşte performans garantisinin kalbi budur. Örneğin $N=1.000.000$ olduğunda zincir biçimli ağaç yaklaşık bir milyon adım gerektirebilirken ağırlıklı ağacın yüksekliği yaklaşık 20 ile sınırlıdır. Algoritmik diyet işe yarıyor: küçük ağaç, büyük ağacın sırtına biniyor!</p>

<h2 id="java-ile-uygulama">Java ile uygulama</h2>

<p>Aşağıdaki sınıf, ebeveynleri <code class="language-plaintext highlighter-rouge">parent</code>, ağaç büyüklüklerini ise <code class="language-plaintext highlighter-rouge">size</code> dizisinde saklar:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">WeightedQuickUnion</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">parent</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">size</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">WeightedQuickUnion</span><span class="o">(</span><span class="kt">int</span> <span class="n">n</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">parent</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="n">n</span><span class="o">];</span>
        <span class="n">size</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="n">n</span><span class="o">];</span>

        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
            <span class="n">parent</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="n">i</span><span class="o">;</span>
            <span class="n">size</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">find</span><span class="o">(</span><span class="kt">int</span> <span class="n">p</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">validate</span><span class="o">(</span><span class="n">p</span><span class="o">);</span>
        <span class="k">while</span> <span class="o">(</span><span class="n">p</span> <span class="o">!=</span> <span class="n">parent</span><span class="o">[</span><span class="n">p</span><span class="o">])</span> <span class="o">{</span>
            <span class="n">p</span> <span class="o">=</span> <span class="n">parent</span><span class="o">[</span><span class="n">p</span><span class="o">];</span>
        <span class="o">}</span>
        <span class="k">return</span> <span class="n">p</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">connected</span><span class="o">(</span><span class="kt">int</span> <span class="n">p</span><span class="o">,</span> <span class="kt">int</span> <span class="n">q</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nf">find</span><span class="o">(</span><span class="n">p</span><span class="o">)</span> <span class="o">==</span> <span class="n">find</span><span class="o">(</span><span class="n">q</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">union</span><span class="o">(</span><span class="kt">int</span> <span class="n">p</span><span class="o">,</span> <span class="kt">int</span> <span class="n">q</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">int</span> <span class="n">rootP</span> <span class="o">=</span> <span class="n">find</span><span class="o">(</span><span class="n">p</span><span class="o">);</span>
        <span class="kt">int</span> <span class="n">rootQ</span> <span class="o">=</span> <span class="n">find</span><span class="o">(</span><span class="n">q</span><span class="o">);</span>

        <span class="k">if</span> <span class="o">(</span><span class="n">rootP</span> <span class="o">==</span> <span class="n">rootQ</span><span class="o">)</span> <span class="k">return</span><span class="o">;</span>

        <span class="k">if</span> <span class="o">(</span><span class="n">size</span><span class="o">[</span><span class="n">rootP</span><span class="o">]</span> <span class="o">&lt;</span> <span class="n">size</span><span class="o">[</span><span class="n">rootQ</span><span class="o">])</span> <span class="o">{</span>
            <span class="n">parent</span><span class="o">[</span><span class="n">rootP</span><span class="o">]</span> <span class="o">=</span> <span class="n">rootQ</span><span class="o">;</span>
            <span class="n">size</span><span class="o">[</span><span class="n">rootQ</span><span class="o">]</span> <span class="o">+=</span> <span class="n">size</span><span class="o">[</span><span class="n">rootP</span><span class="o">];</span>
        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
            <span class="n">parent</span><span class="o">[</span><span class="n">rootQ</span><span class="o">]</span> <span class="o">=</span> <span class="n">rootP</span><span class="o">;</span>
            <span class="n">size</span><span class="o">[</span><span class="n">rootP</span><span class="o">]</span> <span class="o">+=</span> <span class="n">size</span><span class="o">[</span><span class="n">rootQ</span><span class="o">];</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">validate</span><span class="o">(</span><span class="kt">int</span> <span class="n">p</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">p</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">p</span> <span class="o">&gt;=</span> <span class="n">parent</span><span class="o">.</span><span class="na">length</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">();</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">find</code> yalnızca köke yürür. <code class="language-plaintext highlighter-rouge">union</code> önce iki kökü bulur, ardından <code class="language-plaintext highlighter-rouge">size</code> değerlerini karşılaştırarak küçük ağacı büyük ağaca bağlar. Boyut bilgisinin yalnızca köklerde anlamlı olduğuna dikkat edilmelidir.</p>

<h2 id="bir-adım-daha-yol-sıkıştırma">Bir adım daha: yol sıkıştırma</h2>

<p>Performansı daha da artırmak için <code class="language-plaintext highlighter-rouge">find</code> döngüsüne şu satır eklenebilir:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">parent</span><span class="o">[</span><span class="n">p</span><span class="o">]</span> <span class="o">=</span> <span class="n">parent</span><span class="o">[</span><span class="n">parent</span><span class="o">[</span><span class="n">p</span><span class="o">]];</span>
</code></pre></div></div>

<p>Bu işlem, ziyaret edilen düğümü büyük ebeveynine bağlayarak yolu kısaltır. Ağırlıklandırma ağacın baştan fazla uzamasını önlerken yol sıkıştırma mevcut yolları düzleştirir. Birlikte kullanıldıklarında Union-Find işlemleri pratikte sabit zamana yakın çalışır. Sonuç olarak Weighted Quick-Union, küçük bir ek bellek maliyeti karşılığında kontrolsüz ağaç büyümesini engelleyen, basit ama son derece güçlü bir optimizasyondur.</p>

<p><img src="/img/agirlikli-hizli-birlesme-21.svg" alt="agirlikli-hizli-birlesme-21" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="algoritma" /><category term="union-find" /><category term="veri-yapıları" /><category term="java" /><category term="weighted-quick-union" /><summary type="html"><![CDATA[Union-Find, elemanların hangi gruba ait olduğunu hızlıca belirlemek ve iki grubu birleştirmek için kullanılan klasik bir veri yapısıdır. Ancak grupları düşünmeden birleştirirsek ortaya uzun, ince ve performans düşmanı ağaçlar çıkabilir. Ağırlıklı Hızlı-Birleşme (Weighted Quick-Union), küçük ağacı büyük ağacın altına bağlayarak bu sorunu oldukça zarif biçimde çözer.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/agirlikli-hizli-birlesme-21.png" /><media:content medium="image" url="https://program.sonsuz.us/img/agirlikli-hizli-birlesme-21.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Amortize Analiz: Pahalı İşlemleri Uzun Vadede Ucuzlatmak</title><link href="https://program.sonsuz.us/posts/amortize-analiz-pahali-islemleri-uzun-vadede-ucuzlatmak/" rel="alternate" type="text/html" title="Amortize Analiz: Pahalı İşlemleri Uzun Vadede Ucuzlatmak" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/amortize-analiz-pahali-islemleri-uzun-vadede-ucuzlatmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/amortize-analiz-pahali-islemleri-uzun-vadede-ucuzlatmak/"><![CDATA[<p>Bir algoritmadaki tek bir işlemin pahalı olması, algoritmanın genel olarak verimsiz olduğu anlamına gelmez. Bazen nadiren gerçekleşen maliyetli işlemler, çok sayıdaki ucuz işlem arasında kaybolur. Amortize analiz, tam da bu tabloya bakarak bir işlem dizisinin uzun vadeli ortalama maliyetini hesaplamamızı sağlar.</p>

<p>``</p>

<h2 id="amortize-analiz-nedir">Amortize analiz nedir?</h2>

<p>Amortize analiz, bir işlemin olasılıksal ortalamasını değil, <strong>en kötü durumda oluşabilecek işlem dizisinin ortalama maliyetini</strong> inceler. Bu nedenle ortalama durum analizinden farklıdır: Kullanıcı davranışı veya rastgele veri dağılımı hakkında varsayım yapmaz.</p>

<p>$n$ işlemden oluşan bir dizinin toplam maliyeti $T(n)$ ise işlem başına amortize maliyet şöyle hesaplanır:</p>

\[A(n) = \frac{T(n)}{n}\]

<p>Örneğin toplam maliyet $T(n)=3n+10$ ise amortize maliyet:</p>

\[A(n)=\frac{3n+10}{n}=3+\frac{10}{n}=O(1)\]

<p>Burada bazı işlemler tek başına pahalı olsa bile uzun vadede her işlem sabit maliyetli kabul edilebilir.</p>

<table>
  <thead>
    <tr>
      <th>Analiz türü</th>
      <th>İncelenen durum</th>
      <th style="text-align: right">Varsayım gerekir mi?</th>
      <th style="text-align: right">Sonuç örneği</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>En iyi durum</td>
      <td>En avantajlı girdi</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">$\Omega(1)$</td>
    </tr>
    <tr>
      <td>En kötü durum</td>
      <td>En maliyetli tek işlem</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">$O(n)$</td>
    </tr>
    <tr>
      <td>Ortalama durum</td>
      <td>Olası girdilerin ortalaması</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Beklenen maliyet</td>
    </tr>
    <tr>
      <td>Amortize analiz</td>
      <td>En kötü işlem dizisinin ortalaması</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">İşlem başına $O(1)$</td>
    </tr>
  </tbody>
</table>

<h2 id="klasik-örnek-dinamik-dizi">Klasik örnek: Dinamik dizi</h2>

<p>Dinamik bir dizinin kapasitesi dolduğunda daha büyük bir alan ayrılır ve eski elemanlar yeni alana kopyalanır. Normal bir ekleme $O(1)$ sürerken yeniden boyutlandırma işlemi $O(n)$ maliyetli olabilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">DynamicArray</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">capacity</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="n">self</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[</span><span class="bp">None</span><span class="p">]</span> <span class="o">*</span> <span class="n">self</span><span class="p">.</span><span class="n">capacity</span>

    <span class="k">def</span> <span class="nf">append</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">size</span> <span class="o">==</span> <span class="n">self</span><span class="p">.</span><span class="n">capacity</span><span class="p">:</span>
            <span class="n">self</span><span class="p">.</span><span class="nf">_resize</span><span class="p">()</span>

        <span class="n">self</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">size</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
        <span class="n">self</span><span class="p">.</span><span class="n">size</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">_resize</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">capacity</span> <span class="o">*=</span> <span class="mi">2</span>
        <span class="n">new_data</span> <span class="o">=</span> <span class="p">[</span><span class="bp">None</span><span class="p">]</span> <span class="o">*</span> <span class="n">self</span><span class="p">.</span><span class="n">capacity</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">self</span><span class="p">.</span><span class="n">size</span><span class="p">):</span>
            <span class="n">new_data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>

        <span class="n">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">new_data</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">_resize</code>, mevcut elemanları kopyalayarak kapasiteyi iki katına çıkarır. Boyutlandırmalar $1,2,4,8,\ldots$ elemanda gerçekleşir. $n$ ekleme boyunca yapılan toplam kopyalama sayısı:</p>

\[1+2+4+\cdots+\frac{n}{2}&lt;n\]

<p>Normal eklemelerin maliyeti de $n$ olduğundan toplam maliyet $2n$ civarındadır. Böylece işlem başına maliyet:</p>

\[\frac{2n}{n}=O(1)\]

<p>Tek bir ekleme $O(n)$ sürebilir; ancak <code class="language-plaintext highlighter-rouge">append</code> işleminin amortize maliyeti $O(1)$ olur. Pahalı taşınma masrafı, önceki ucuz eklemelere dağıtılmıştır.</p>

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

<h3 id="1-toplam-maliyet-yöntemi">1. Toplam maliyet yöntemi</h3>

<p>Tüm işlem dizisinin gerçek maliyeti hesaplanır ve işlem sayısına bölünür. Dinamik dizi örneğinde kullandığımız yaklaşım budur.</p>

<h3 id="2-muhasebe-yöntemi">2. Muhasebe yöntemi</h3>

<p>Ucuz işlemlerden gerçek maliyetlerinden biraz daha fazla ücret alınır. Aradaki kredi, gelecekteki pahalı işlemleri karşılamak üzere saklanır. Bir eklemenin gerçek maliyeti $1$ olsa da ona $3$ kredi biçtiğimizi düşünebiliriz. Fazladan kalan krediler yeniden boyutlandırmayı öder; algoritma adeta kendi kumbarasını taşır.</p>

<h3 id="3-potansiyel-yöntemi">3. Potansiyel yöntemi</h3>

<p>Veri yapısında biriken gelecekteki işi matematiksel bir potansiyel fonksiyonuyla gösteririz. Amortize maliyet:</p>

\[\hat{c_i}=c_i+\Phi(D_i)-\Phi(D_{i-1})\]

<p>Burada $c_i$ gerçek maliyet, $\Phi(D_i)$ ise işlemden sonraki potansiyeldir. Potansiyel artıyorsa geleceğe kredi bırakılır; azalıyorsa biriktirilen kredi pahalı işlemi karşılar.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th>Temel fikir</th>
      <th>Kullanışlı olduğu durum</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Toplam</td>
      <td>Bütün maliyeti işlemlere böl</td>
      <td>Düzenli işlem dizileri</td>
    </tr>
    <tr>
      <td>Muhasebe</td>
      <td>Fazla ücretle kredi biriktir</td>
      <td>Sezgisel açıklamalar</td>
    </tr>
    <tr>
      <td>Potansiyel</td>
      <td>Veri yapısındaki enerjiyi ölç</td>
      <td>Karmaşık yapılar ve ispatlar</td>
    </tr>
  </tbody>
</table>

<p>Amortize analiz, tek bir kötü ana bakıp paniğe kapılmak yerine filmin tamamını izler. Dinamik diziler, hash tabloları, yığıt işlemleri ve birleşim-bulma yapıları bu yöntemle daha doğru değerlendirilir. Kısacası soru yalnızca “Bu işlem ne kadar pahalı?” değil, “Bu maliyet uzun bir yolculuk boyunca kaç işleme paylaşılıyor?” olmalıdır.</p>

<p><img src="/img/amortize-analiz-pahali-93.svg" alt="amortize-analiz-pahali-93" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="amortize analiz" /><category term="algoritma" /><category term="veri yapıları" /><category term="zaman karmaşıklığı" /><category term="dinamik dizi" /><summary type="html"><![CDATA[Bir algoritmadaki tek bir işlemin pahalı olması, algoritmanın genel olarak verimsiz olduğu anlamına gelmez. Bazen nadiren gerçekleşen maliyetli işlemler, çok sayıdaki ucuz işlem arasında kaybolur. Amortize analiz, tam da bu tabloya bakarak bir işlem dizisinin uzun vadeli ortalama maliyetini hesaplamamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/amortize-analiz-pahali-93.png" /><media:content medium="image" url="https://program.sonsuz.us/img/amortize-analiz-pahali-93.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Aynı Seçim, Farklı Kazanan: Borda ve Condorcet Yöntemleri</title><link href="https://program.sonsuz.us/posts/ayni-secim-farkli-kazanan-borda-ve-condorcet-yontemleri/" rel="alternate" type="text/html" title="Aynı Seçim, Farklı Kazanan: Borda ve Condorcet Yöntemleri" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/ayni-secim-farkli-kazanan-borda-ve-condorcet-yontemleri</id><content type="html" xml:base="https://program.sonsuz.us/posts/ayni-secim-farkli-kazanan-borda-ve-condorcet-yontemleri/"><![CDATA[<p>Bir seçimde en çok oyu alan adayın kazanacağını düşünmek doğaldır. Ancak seçmenler yalnızca tek aday belirtmek yerine adayları tercih sırasına koyduğunda işler değişir. Oyları nasıl puanladığımız veya adayları nasıl karşılaştırdığımız, aynı tercihlerden farklı kazananlar çıkarabilir. Borda ve Condorcet yöntemleri, bu şaşırtıcı durumun en güzel örneklerindendir.</p>

<p>``</p>

<h2 id="tercihli-oylamanın-temel-fikri">Tercihli oylamanın temel fikri</h2>

<p>Üç adayımız olsun: Ada, Bora ve Ceren. Seçmenlerden adayları en beğendiklerinden en az beğendiklerine doğru sıralamalarını isteyelim. Sonuçlar şöyle olsun:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Seçmen sayısı</th>
      <th>1. tercih</th>
      <th>2. tercih</th>
      <th>3. tercih</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">4</td>
      <td>Ada</td>
      <td>Bora</td>
      <td>Ceren</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Bora</td>
      <td>Ceren</td>
      <td>Ada</td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>Ceren</td>
      <td>Bora</td>
      <td>Ada</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/ayni-secim-farkli-60.svg" alt="ayni-secim-farkli-60" /></p>

<p>Burada yalnızca birinci tercihlere bakarsak Ada 4, Bora 3, Ceren 2 oy alır. Basit çoğulluk yöntemi Ada’yı kazanan ilan eder. Fakat sıralamanın geri kalanını da hesaba katarsak sonuç değişebilir.</p>

<h2 id="borda-sayımı-her-sıraya-puan">Borda sayımı: Her sıraya puan</h2>

<p>Borda yönteminde adaylar bulundukları sıraya göre puan kazanır. $m$ aday varsa birinci sıraya $m-1$, ikinci sıraya $m-2$ ve son sıraya $0$ puan verilebilir. Üç aday için puanlar sırasıyla $2$, $1$ ve $0$ olur.</p>

<p>Bir adayın toplam Borda puanı şu şekilde ifade edilir:</p>

\[B(a)=\sum_{i=1}^{n} p_i(a)\]

<p>Burada $p_i(a)$, $i$ numaralı seçmenin $a$ adayına verdiği sıra puanıdır. Örneğimizde puanlar şöyledir:</p>

<table>
  <thead>
    <tr>
      <th>Aday</th>
      <th>Puan hesabı</th>
      <th style="text-align: right">Toplam</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ada</td>
      <td>$4\times2+3\times0+2\times0$</td>
      <td style="text-align: right">8</td>
    </tr>
    <tr>
      <td>Bora</td>
      <td>$4\times1+3\times2+2\times1$</td>
      <td style="text-align: right">12</td>
    </tr>
    <tr>
      <td>Ceren</td>
      <td>$4\times0+3\times1+2\times2$</td>
      <td style="text-align: right">7</td>
    </tr>
  </tbody>
</table>

<p>Borda kazananı Bora’dır. Ada daha fazla seçmenin ilk tercihi olmasına rağmen birçok seçmen tarafından son sıraya konmuştur. Bora ise geniş bir uzlaşma sağlamıştır. Borda, güçlü sevgiyi ödüllendirirken genel kabulü de önemser.</p>

<h2 id="condorcet-bire-bir-düello">Condorcet: Bire bir düello</h2>

<p>Condorcet yaklaşımı puan toplamak yerine adayları ikili karşılaştırır. Bir aday, diğer bütün adayları bire bir seçimlerde yeniyorsa <strong>Condorcet kazananı</strong> olur.</p>

<p>Örneğin Bora ile Ada karşılaştırıldığında ilk gruptaki 4 seçmen Ada’yı, diğer 5 seçmen Bora’yı üstün tutar. Bora, Ada’yı $5$–$4$ yener. Bora ile Ceren karşılaşmasında ise ilk iki grup, yani 7 seçmen Bora’yı Ceren’in önüne koyar. Böylece Bora yine kazanır ve Condorcet kazananı olur.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th>Neye odaklanır?</th>
      <th>Bu örnekte kazanan</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Basit çoğulluk</td>
      <td>Birinci tercihler</td>
      <td>Ada</td>
    </tr>
    <tr>
      <td>Borda</td>
      <td>Tüm sıraların puanı</td>
      <td>Bora</td>
    </tr>
    <tr>
      <td>Condorcet</td>
      <td>İkili karşılaşmalar</td>
      <td>Bora</td>
    </tr>
  </tbody>
</table>

<p>Borda ve Condorcet her zaman aynı sonucu vermez. Ayrıca Condorcet kazananı bulunmayabilir: Ada Bora’yı, Bora Ceren’i, Ceren de Ada’yı yenebilir. Bu duruma <strong>Condorcet döngüsü</strong> denir; tercihler taş-kâğıt-makas oyununa dönüşür.</p>

<h2 id="küçük-bir-python-uygulaması">Küçük bir Python uygulaması</h2>

<p>Aşağıdaki kod, sıralı oyların Borda puanlarını hesaplar:</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">defaultdict</span>

<span class="n">oylar</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="p">[</span><span class="sh">"</span><span class="s">Ada</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">Bora</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">Ceren</span><span class="sh">"</span><span class="p">]),</span>
    <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="p">[</span><span class="sh">"</span><span class="s">Bora</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">Ceren</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">Ada</span><span class="sh">"</span><span class="p">]),</span>
    <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">[</span><span class="sh">"</span><span class="s">Ceren</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">Bora</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">Ada</span><span class="sh">"</span><span class="p">]),</span>
<span class="p">]</span>

<span class="n">puanlar</span> <span class="o">=</span> <span class="nf">defaultdict</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
<span class="n">aday_sayisi</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">oylar</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="k">for</span> <span class="n">secmen</span><span class="p">,</span> <span class="n">siralama</span> <span class="ow">in</span> <span class="n">oylar</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">sira</span><span class="p">,</span> <span class="n">aday</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">siralama</span><span class="p">):</span>
        <span class="n">puanlar</span><span class="p">[</span><span class="n">aday</span><span class="p">]</span> <span class="o">+=</span> <span class="n">secmen</span> <span class="o">*</span> <span class="p">(</span><span class="n">aday_sayisi</span> <span class="o">-</span> <span class="n">sira</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">dict</span><span class="p">(</span><span class="n">puanlar</span><span class="p">))</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Kazanan:</span><span class="sh">"</span><span class="p">,</span> <span class="nf">max</span><span class="p">(</span><span class="n">puanlar</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">puanlar</span><span class="p">.</span><span class="n">get</span><span class="p">))</span>
</code></pre></div></div>

<p>Döngü, her adayın sıra puanını o tercihi paylaşan seçmen sayısıyla çarpar. Çıktıda Bora 12 puanla kazanır.</p>

<p>Sonuç olarak seçim yöntemi tarafsız bir ayrıntı değil, sonucun parçasıdır. Basit çoğulluk güçlü birinci tercihleri, Borda genel memnuniyeti, Condorcet ise bire bir üstünlüğü ölçer. Bu nedenle “Kim kazandı?” sorusundan önce “Oyları hangi kuralla saydık?” diye sormak gerekir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="oylama" /><category term="borda" /><category term="condorcet" /><category term="sosyal-seçim" /><category term="algoritma" /><category term="matematik" /><summary type="html"><![CDATA[Bir seçimde en çok oyu alan adayın kazanacağını düşünmek doğaldır. Ancak seçmenler yalnızca tek aday belirtmek yerine adayları tercih sırasına koyduğunda işler değişir. Oyları nasıl puanladığımız veya adayları nasıl karşılaştırdığımız, aynı tercihlerden farklı kazananlar çıkarabilir. Borda ve Condorcet yöntemleri, bu şaşırtıcı durumun en güzel örneklerindendir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/ayni-secim-farkli-60.png" /><media:content medium="image" url="https://program.sonsuz.us/img/ayni-secim-farkli-60.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Bellman-Ford ile Döviz Arbitrajı: Negatif Döngülerden Kâr Fırsatlarına</title><link href="https://program.sonsuz.us/posts/bellman-ford-ile-doviz-arbitraji-negatif-dongulerden-kar-firsatlarina/" rel="alternate" type="text/html" title="Bellman-Ford ile Döviz Arbitrajı: Negatif Döngülerden Kâr Fırsatlarına" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/bellman-ford-ile-doviz-arbitraji-negatif-dongulerden-kar-firsatlarina</id><content type="html" xml:base="https://program.sonsuz.us/posts/bellman-ford-ile-doviz-arbitraji-negatif-dongulerden-kar-firsatlarina/"><![CDATA[<p>Bir para birimini diğerine, onu da başka bir para birimine çevirip başlangıçtaki paranızdan daha fazlasıyla geri dönebilir misiniz? Teorik olarak evet! <strong>Arbitraj</strong>, farklı döviz kurları arasındaki tutarsızlıklardan risksiz kâr elde etme fikridir. Bu finans problemini bir graf problemine dönüştürdüğümüzde ise sahneye Bellman-Ford algoritması ve onun meşhur negatif döngü tespiti çıkar.</p>

<p>``</p>

<h2 id="döviz-piyasasını-graf-olarak-modellemek">Döviz piyasasını graf olarak modellemek</h2>

<p>Her para birimini bir <strong>düğüm</strong>, mümkün olan her döviz dönüşümünü de yönlü bir <strong>kenar</strong> olarak düşünebiliriz. Örneğin USD’den EUR’ya geçiş ayrı, EUR’dan USD’ye geçiş ayrı bir kenardır; çünkü bu iki kur birbirinin tam tersi olmak zorunda değildir.</p>

<p>Elimizde şu dönüşüm zinciri olsun:</p>

\[USD \rightarrow EUR \rightarrow GBP \rightarrow USD\]

<p>Başlangıçta 1 USD varsa zincirin sonunda elde edeceğimiz miktar:</p>

\[1 \times r_{USD,EUR} \times r_{EUR,GBP} \times r_{GBP,USD}\]

<p>Kurların çarpımı 1’den büyükse başlangıçtakinden daha fazla USD elde ederiz:</p>

\[r_1 \times r_2 \times \cdots \times r_n &gt; 1\]

<p>Ancak graf algoritmaları toplama işlemleriyle çalışmayı sever. Çarpımları toplama çevirmek için logaritmadan yararlanırız:</p>

\[w(u,v) = -\ln(r_{u,v})\]

<p>Negatif logaritma uygulandığında kârlılık koşulu şu hâle gelir:</p>

\[\sum w_i &lt; 0\]

<p>Yani arbitraj fırsatı, dönüştürülmüş graf üzerindeki <strong>negatif ağırlıklı bir döngüdür</strong>.</p>

<table>
  <thead>
    <tr>
      <th>Finans kavramı</th>
      <th>Graf karşılığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Para birimi</td>
      <td>Düğüm</td>
    </tr>
    <tr>
      <td>Döviz dönüşümü</td>
      <td>Yönlü kenar</td>
    </tr>
    <tr>
      <td>Döviz kuru</td>
      <td>Kenar ağırlığının kaynağı</td>
    </tr>
    <tr>
      <td>Kârlı dönüşüm zinciri</td>
      <td>Negatif döngü</td>
    </tr>
    <tr>
      <td>Komisyon</td>
      <td>Efektif kurda azalma</td>
    </tr>
  </tbody>
</table>

<h2 id="neden-bellman-ford">Neden Bellman-Ford?</h2>

<p>Dijkstra algoritması negatif kenar ağırlıklarıyla güvenilir biçimde çalışmaz. Bellman-Ford ise negatif ağırlıkları destekler ve ulaşılabilir negatif döngüleri belirleyebilir.</p>

<p>Algoritma, $V$ düğümlü bir grafta bütün kenarları $V-1$ kez gevşetir. Bu işlemlerden sonra herhangi bir mesafe hâlâ küçültülebiliyorsa negatif döngü vardır. Zaman karmaşıklığı $O(VE)$ seviyesindedir; para birimi sayısının genellikle sınırlı olması nedeniyle pratik bir seçimdir.</p>

<table>
  <thead>
    <tr>
      <th>Algoritma</th>
      <th style="text-align: right">Negatif kenar</th>
      <th style="text-align: right">Negatif döngü tespiti</th>
      <th style="text-align: right">Karmaşıklık</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dijkstra</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">$O(E\log V)$</td>
    </tr>
    <tr>
      <td>Bellman-Ford</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">$O(VE)$</td>
    </tr>
    <tr>
      <td>Floyd-Warshall</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">$O(V^3)$</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-arbitraj-tespiti">Python ile arbitraj tespiti</h2>

<p>Aşağıdaki fonksiyon kurları negatif logaritmik ağırlıklara dönüştürür. Bütün düğümlerin başlangıç mesafesini sıfır yapmak, bağlantısız bileşenlerdeki döngüleri de aramamızı sağlar.</p>

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


<span class="k">def</span> <span class="nf">find_arbitrage</span><span class="p">(</span><span class="n">currencies</span><span class="p">,</span> <span class="n">rates</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">currencies</span><span class="p">)</span>
    <span class="n">edges</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">for</span> <span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">rate</span> <span class="ow">in</span> <span class="n">rates</span><span class="p">:</span>
        <span class="n">weight</span> <span class="o">=</span> <span class="o">-</span><span class="n">math</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="n">rate</span><span class="p">)</span>
        <span class="n">edges</span><span class="p">.</span><span class="nf">append</span><span class="p">((</span><span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">weight</span><span class="p">))</span>

    <span class="n">distance</span> <span class="o">=</span> <span class="p">[</span><span class="mf">0.0</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span>
    <span class="n">parent</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span>
    <span class="n">changed</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</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="n">n</span><span class="p">):</span>
        <span class="n">changed</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
        <span class="k">for</span> <span class="n">source</span><span class="p">,</span> <span class="n">target</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">distance</span><span class="p">[</span><span class="n">target</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">distance</span><span class="p">[</span><span class="n">source</span><span class="p">]</span> <span class="o">+</span> <span class="n">weight</span><span class="p">:</span>
                <span class="n">distance</span><span class="p">[</span><span class="n">target</span><span class="p">]</span> <span class="o">=</span> <span class="n">distance</span><span class="p">[</span><span class="n">source</span><span class="p">]</span> <span class="o">+</span> <span class="n">weight</span>
                <span class="n">parent</span><span class="p">[</span><span class="n">target</span><span class="p">]</span> <span class="o">=</span> <span class="n">source</span>
                <span class="n">changed</span> <span class="o">=</span> <span class="n">target</span>

    <span class="k">if</span> <span class="n">changed</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">None</span>

    <span class="c1"># Düğümü döngünün içine taşır.
</span>    <span class="n">vertex</span> <span class="o">=</span> <span class="n">changed</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="n">n</span><span class="p">):</span>
        <span class="n">vertex</span> <span class="o">=</span> <span class="n">parent</span><span class="p">[</span><span class="n">vertex</span><span class="p">]</span>

    <span class="n">cycle</span> <span class="o">=</span> <span class="p">[</span><span class="n">vertex</span><span class="p">]</span>
    <span class="n">current</span> <span class="o">=</span> <span class="n">parent</span><span class="p">[</span><span class="n">vertex</span><span class="p">]</span>
    <span class="k">while</span> <span class="n">current</span> <span class="o">!=</span> <span class="n">vertex</span><span class="p">:</span>
        <span class="n">cycle</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">current</span><span class="p">)</span>
        <span class="n">current</span> <span class="o">=</span> <span class="n">parent</span><span class="p">[</span><span class="n">current</span><span class="p">]</span>

    <span class="n">cycle</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">vertex</span><span class="p">)</span>
    <span class="n">cycle</span><span class="p">.</span><span class="nf">reverse</span><span class="p">()</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">currencies</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">cycle</span><span class="p">]</span>


<span class="n">currencies</span> <span class="o">=</span> <span class="p">[</span><span class="sh">"</span><span class="s">USD</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">EUR</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">GBP</span><span class="sh">"</span><span class="p">]</span>
<span class="n">rates</span> <span class="o">=</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="mf">0.92</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mf">0.87</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">1.27</span><span class="p">),</span>
<span class="p">]</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">find_arbitrage</span><span class="p">(</span><span class="n">currencies</span><span class="p">,</span> <span class="n">rates</span><span class="p">))</span>
</code></pre></div></div>

<p>Fonksiyon <code class="language-plaintext highlighter-rouge">None</code> döndürürse negatif döngü bulunamamıştır. Bir liste döndürürse listedeki para birimleri olası arbitraj rotasını gösterir. Örnekte kurların çarpımı yaklaşık $0.92 \times 0.87 \times 1.27 = 1.016$ olduğundan teorik olarak yüzde 1,6 civarında brüt kazanç vardır.</p>

<h2 id="gerçek-hayattaki-küçük-ama-önemli-canavarlar">Gerçek hayattaki küçük ama önemli canavarlar</h2>

<p>Teorik arbitraj ile uygulanabilir arbitraj aynı şey değildir. Alış-satış farkı, işlem komisyonu, ağ gecikmesi, likidite ve kur değişimleri kârı yok edebilir. Komisyon oranı $c$ ise dönüşümde çıplak kur yerine efektif kur kullanılmalıdır:</p>

\[r_{efektif} = r(1-c)\]

<p>Ayrıca kayan nokta hataları yüzünden karşılaştırmalara küçük bir tolerans eklemek faydalıdır. Bellman-Ford fırsatı matematiksel olarak bulur; fırsatın gerçekten cüzdanınıza ulaşması ise veri kalitesine ve işlem hızına bağlıdır. Kısacası algoritma hazine haritasını çizer, fakat hazinenin yerinde duracağını garanti etmez!</p>

<p><img src="/img/bellman-ford-ile-81.svg" alt="bellman-ford-ile-81" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="bellman-ford" /><category term="algoritma" /><category term="graf teorisi" /><category term="arbitraj" /><category term="python" /><category term="finans" /><summary type="html"><![CDATA[Bir para birimini diğerine, onu da başka bir para birimine çevirip başlangıçtaki paranızdan daha fazlasıyla geri dönebilir misiniz? Teorik olarak evet! Arbitraj, farklı döviz kurları arasındaki tutarsızlıklardan risksiz kâr elde etme fikridir. Bu finans problemini bir graf problemine dönüştürdüğümüzde ise sahneye Bellman-Ford algoritması ve onun meşhur negatif döngü tespiti çıkar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/bellman-ford-ile-81.png" /><media:content medium="image" url="https://program.sonsuz.us/img/bellman-ford-ile-81.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">DAG’larda En Kısa Yol: Döngüler Olmadan Daha Hızlı Rotalar</title><link href="https://program.sonsuz.us/posts/daglarda-en-kisa-yol-donguler-olmadan-daha-hizli-rotalar/" rel="alternate" type="text/html" title="DAG’larda En Kısa Yol: Döngüler Olmadan Daha Hızlı Rotalar" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/daglarda-en-kisa-yol-donguler-olmadan-daha-hizli-rotalar</id><content type="html" xml:base="https://program.sonsuz.us/posts/daglarda-en-kisa-yol-donguler-olmadan-daha-hizli-rotalar/"><![CDATA[<p>Bir şehir haritasında sürekli aynı kavşağa dönebiliyorsanız rota bulmak biraz baş ağrıtabilir. Yönlendirilmiş Asiklik Graf (Directed Acyclic Graph veya DAG) ise bu karmaşayı ortadan kaldırır: Okları takip ederek başladığınız düğüme geri dönemezsiniz. Bu döngüsüz yapı sayesinde en kısa yolları, Dijkstra’nın öncelik kuyruğuna bile ihtiyaç duymadan oldukça zarif biçimde hesaplayabiliriz.</p>

<p><img src="/img/daglarda-en-kisa-47.svg" alt="daglarda-en-kisa-47" /></p>

<p>``</p>

<h2 id="önce-dag-nedir">Önce DAG nedir?</h2>

<p>Yönlendirilmiş bir grafta kenarlar belirli bir yöne sahiptir. Örneğin $u \rightarrow v$ kenarı, yalnızca $u$ düğümünden $v$ düğümüne geçişi temsil eder. Grafın içinde yönlendirilmiş hiçbir döngü bulunmuyorsa bu yapı bir DAG’dır.</p>

<p>DAG’lar; görev planlama, ders ön koşulları, bağımlılık yönetimi, veri işleme hatları ve sürüm geçmişleri gibi doğal bir ilerleme sırası bulunan problemlerde sıkça görülür.</p>

<p>Döngünün bulunmaması, düğümleri <strong>topolojik olarak sıralayabilmemizi</strong> sağlar. Böyle bir sıralamada her $u \rightarrow v$ kenarı için $u$, listede $v$’den önce gelir. En kısa yol algoritmasının asıl süper gücü de budur.</p>

<h2 id="neden-topolojik-sıralama-yeterli">Neden topolojik sıralama yeterli?</h2>

<p>Başlangıç düğümünün uzaklığını $0$, diğer bütün uzaklıkları $∞$ kabul edelim. Düğümleri topolojik sırayla işlerken her kenar için gevşetme yaparız:</p>

\[d[v] = \min(d[v],\ d[u] + w(u,v))\]

<p>Burada $d[u]$, başlangıçtan $u$ düğümüne bilinen en kısa uzaklık; $w(u,v)$ ise kenarın ağırlığıdır. Bir düğüm işlendiğinde ona gelebilecek bütün önceki düğümler zaten değerlendirilmiştir. Dolayısıyla geriye dönüp uzaklığı tekrar tekrar düzeltmeye gerek kalmaz.</p>

<table>
  <thead>
    <tr>
      <th>Algoritma</th>
      <th style="text-align: right">Negatif kenar</th>
      <th style="text-align: right">Döngü desteği</th>
      <th style="text-align: right">Zaman karmaşıklığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>DAG en kısa yol</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">$O(V+E)$</td>
    </tr>
    <tr>
      <td>Dijkstra</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Genellikle $O((V+E)\log V)$</td>
    </tr>
    <tr>
      <td>Bellman-Ford</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">$O(VE)$</td>
    </tr>
  </tbody>
</table>

<p>DAG algoritması negatif ağırlıklı kenarlarla da çalışır. Çünkü negatif bir kenarın uzaklıkları sonradan beklenmedik biçimde değiştireceği döngüsel bir geri dönüş yoktur. Negatif döngü zaten DAG tanımı gereği oluşamaz.</p>

<h2 id="python-ile-uygulama">Python ile uygulama</h2>

<p>Aşağıdaki fonksiyon önce DFS kullanarak topolojik sıralamayı oluşturur, ardından düğümleri bu sırada işleyerek kenarları gevşetir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">dag_shortest_path</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">order</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">dfs</span><span class="p">(</span><span class="n">node</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">node</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">neighbor</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">node</span><span class="p">,</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="nf">dfs</span><span class="p">(</span><span class="n">neighbor</span><span class="p">)</span>
        <span class="n">order</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>

    <span class="c1"># Bağlantısız parçalar için tüm düğümleri dolaşır.
</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="k">if</span> <span class="n">node</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="nf">dfs</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>

    <span class="n">order</span><span class="p">.</span><span class="nf">reverse</span><span class="p">()</span>
    <span class="n">distance</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">distance</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">order</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">distance</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">==</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">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="nf">get</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="p">[]):</span>
            <span class="n">candidate</span> <span class="o">=</span> <span class="n">distance</span><span class="p">[</span><span class="n">node</span><span class="p">]</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">distance</span><span class="p">[</span><span class="n">neighbor</span><span class="p">]:</span>
                <span class="n">distance</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="k">return</span> <span class="n">distance</span>


<span class="n">graph</span> <span class="o">=</span> <span class="p">{</span>
    <span class="sh">'</span><span class="s">A</span><span class="sh">'</span><span class="p">:</span> <span class="p">[(</span><span class="sh">'</span><span class="s">B</span><span class="sh">'</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="p">(</span><span class="sh">'</span><span class="s">C</span><span class="sh">'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)],</span>
    <span class="sh">'</span><span class="s">B</span><span class="sh">'</span><span class="p">:</span> <span class="p">[(</span><span class="sh">'</span><span class="s">D</span><span class="sh">'</span><span class="p">,</span> <span class="mi">3</span><span class="p">)],</span>
    <span class="sh">'</span><span class="s">C</span><span class="sh">'</span><span class="p">:</span> <span class="p">[(</span><span class="sh">'</span><span class="s">B</span><span class="sh">'</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="sh">'</span><span class="s">D</span><span class="sh">'</span><span class="p">,</span> <span class="mi">5</span><span class="p">)],</span>
    <span class="sh">'</span><span class="s">D</span><span class="sh">'</span><span class="p">:</span> <span class="p">[]</span>
<span class="p">}</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">dag_shortest_path</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="sh">'</span><span class="s">A</span><span class="sh">'</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">C → B</code> kenarının ağırlığı negatiftir. Buna rağmen sonuç güvenle hesaplanır: <code class="language-plaintext highlighter-rouge">A → C → B → D</code> rotasının toplam maliyeti $2 + (-1) + 3 = 4$ olur. Doğrudan görünen yollar her zaman en hesaplı yollar değildir!</p>

<h2 id="karmaşıklık-ve-önemli-ayrıntılar">Karmaşıklık ve önemli ayrıntılar</h2>

<p>Topolojik sıralama $O(V+E)$, bütün kenarların gevşetilmesi de $O(V+E)$ sürer. Böylece toplam zaman karmaşıklığı $O(V+E)$, ek alan gereksinimi ise $O(V)$ olur. Bu, grafın tamamını en azından bir kez incelemek zorunda olduğumuz düşünüldüğünde oldukça verimlidir.</p>

<p>Ancak algoritmayı kullanmadan önce grafın gerçekten asiklik olduğu doğrulanmalıdır. Döngü varsa topolojik sıralama üretilemez. Kahn algoritması sonunda işlenen düğüm sayısını kontrol etmek veya DFS sırasında renk tabanlı döngü tespiti yapmak bu doğrulama için uygundur.</p>

<p>Özetle DAG yapısı, “ilerideki bir düğüm geçmişi etkileyemez” garantisi verir. Bu garanti en kısa yol problemini tek yönlü, doğrusal ve hızlı bir hesaplamaya dönüştürür; bazen döngülerin yokluğu gerçekten de hayatı kolaylaştırır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="dag" /><category term="graf teorisi" /><category term="en kısa yol" /><category term="topolojik sıralama" /><category term="algoritmalar" /><category term="python" /><summary type="html"><![CDATA[Bir şehir haritasında sürekli aynı kavşağa dönebiliyorsanız rota bulmak biraz baş ağrıtabilir. Yönlendirilmiş Asiklik Graf (Directed Acyclic Graph veya DAG) ise bu karmaşayı ortadan kaldırır: Okları takip ederek başladığınız düğüme geri dönemezsiniz. Bu döngüsüz yapı sayesinde en kısa yolları, Dijkstra’nın öncelik kuyruğuna bile ihtiyaç duymadan oldukça zarif biçimde hesaplayabiliriz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/daglarda-en-kisa-47.png" /><media:content medium="image" url="https://program.sonsuz.us/img/daglarda-en-kisa-47.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dizgi Sıralamada Hızlı İkili: LSD ve MSD Algoritmaları</title><link href="https://program.sonsuz.us/posts/dizgi-siralamada-hizli-ikili-lsd-ve-msd-algoritmalari/" rel="alternate" type="text/html" title="Dizgi Sıralamada Hızlı İkili: LSD ve MSD Algoritmaları" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dizgi-siralamada-hizli-ikili-lsd-ve-msd-algoritmalari</id><content type="html" xml:base="https://program.sonsuz.us/posts/dizgi-siralamada-hizli-ikili-lsd-ve-msd-algoritmalari/"><![CDATA[<p>Bir sözlükteki milyonlarca kelimeyi sıralamanız gerektiğini düşünün. Klasik algoritmalar kelimeleri tekrar tekrar karşılaştırırken LSD ve MSD, karakterleri doğrudan anahtar olarak kullanır. Böylece “hangisi küçük?” sorusunu sürekli sormak yerine karakterlerin dağılımından yararlanırlar. Sonuç, uygun koşullarda karşılaştırmalı sıralamalardan belirgin biçimde daha hızlı çalışan bir yaklaşımdır.</p>

<p><img src="/img/dizgi-siralamada-hizli-55.svg" alt="dizgi-siralamada-hizli-55" /></p>

<p>``</p>
<h2 id="karşılaştırma-olmadan-sıralama-fikri">Karşılaştırma Olmadan Sıralama Fikri</h2>

<p>Quick Sort, Merge Sort ve Heap Sort gibi klasik algoritmalar karşılaştırma tabanlıdır. Bu algoritmaların genel alt sınırı $\Omega(N \log N)$ karşılaştırmadır. Dizgi sıralamada her karşılaştırma birden fazla karakterin incelenmesini gerektirebildiği için gerçek maliyet daha da büyüyebilir.</p>

<p>Anahtar-indeks sayımı ise karakterleri, örneğin ASCII kodlarını, küçük tam sayılara dönüştürür. Alfabe büyüklüğü $R$, eleman sayısı $N$ olduğunda tek karakter için temel süreç şöyledir:</p>

<ol>
  <li>Her karakterin kaç kez geçtiğini say.</li>
  <li>Sayımları başlangıç indekslerine dönüştür.</li>
  <li>Öğeleri yardımcı diziye dağıt.</li>
  <li>Sonucu ana diziye geri kopyala.</li>
</ol>

<p>Bu işlemin zaman karmaşıklığı $O(N + R)$ olur. Buradaki önemli ayrıntı, dağıtımın <strong>kararlı</strong> olmasıdır: Aynı karaktere sahip öğelerin önceki göreli sırası korunur.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">counting_sort_by_char</span><span class="p">(</span><span class="n">words</span><span class="p">,</span> <span class="n">index</span><span class="p">,</span> <span class="n">alphabet_size</span><span class="o">=</span><span class="mi">256</span><span class="p">):</span>
    <span class="n">count</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">alphabet_size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="bp">None</span><span class="p">]</span> <span class="o">*</span> <span class="nf">len</span><span class="p">(</span><span class="n">words</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">:</span>
        <span class="n">code</span> <span class="o">=</span> <span class="nf">ord</span><span class="p">(</span><span class="n">word</span><span class="p">[</span><span class="n">index</span><span class="p">])</span>
        <span class="n">count</span><span class="p">[</span><span class="n">code</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">alphabet_size</span><span class="p">):</span>
        <span class="n">count</span><span class="p">[</span><span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">count</span><span class="p">[</span><span class="n">r</span><span class="p">]</span>

    <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">:</span>
        <span class="n">code</span> <span class="o">=</span> <span class="nf">ord</span><span class="p">(</span><span class="n">word</span><span class="p">[</span><span class="n">index</span><span class="p">])</span>
        <span class="n">output</span><span class="p">[</span><span class="n">count</span><span class="p">[</span><span class="n">code</span><span class="p">]]</span> <span class="o">=</span> <span class="n">word</span>
        <span class="n">count</span><span class="p">[</span><span class="n">code</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

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

<p>Bu yardımcı fonksiyon, sabit bir karakter konumuna göre kararlı sıralama yapar. <code class="language-plaintext highlighter-rouge">count</code> dizisindeki bir hücre frekansı, ön toplam işleminden sonra ise başlangıç konumunu temsil eder.</p>

<h2 id="lsd-sağdan-sola-i̇lerlemek">LSD: Sağdan Sola İlerlemek</h2>

<p>LSD, yani <em>Least Significant Digit</em>, en sağdaki karakterden başlar ve sola doğru ilerler. Genellikle tüm anahtarların aynı uzunlukta olduğu durumlarda kullanılır. Plaka kodları, sabit uzunluklu kimlikler ve tarih biçimleri iyi örneklerdir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">lsd_sort</span><span class="p">(</span><span class="n">words</span><span class="p">,</span> <span class="n">width</span><span class="p">):</span>
    <span class="n">result</span> <span class="o">=</span> <span class="nf">list</span><span class="p">(</span><span class="n">words</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">width</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
        <span class="n">result</span> <span class="o">=</span> <span class="nf">counting_sort_by_char</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">result</span>

<span class="n">codes</span> <span class="o">=</span> <span class="p">[</span><span class="sh">'</span><span class="s">B12</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">A90</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">B01</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">A12</span><span class="sh">'</span><span class="p">]</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">lsd_sort</span><span class="p">(</span><span class="n">codes</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
</code></pre></div></div>

<p>Sağdan başlanmasının nedeni kararlılıktır. Son basamağa göre oluşan düzen, daha önemli bir karakter işlendiğinde aynı karakterli grupların içinde korunur. $W$ karakterli $N$ dizgi için yaklaşık maliyet $O(W(N + R))$ seviyesindedir.</p>

<h2 id="msd-soldan-başlayan-böl-ve-yönet">MSD: Soldan Başlayan Böl ve Yönet</h2>

<p>MSD, yani <em>Most Significant Digit</em>, önce en soldaki karakteri işler. Ardından aynı karakterle başlayan grupları kendi içlerinde özyinelemeli olarak sıralar. Değişken uzunluktaki kelimelerde özel bir “karakter yok” değeri kullanılır.</p>

<p>Örneğin <code class="language-plaintext highlighter-rouge">ar</code>, <code class="language-plaintext highlighter-rouge">ara</code> ve <code class="language-plaintext highlighter-rouge">armut</code> karşılaştırılırken kısa kelimenin bittiğini gösteren değer, gerçek karakterlerden küçük kabul edilir. Böylece <code class="language-plaintext highlighter-rouge">ar</code>, diğer ikisinin önüne gelir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>LSD</th>
      <th>MSD</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Başlangıç yönü</td>
      <td>Sağdan sola</td>
      <td>Soldan sağa</td>
    </tr>
    <tr>
      <td>Uygun anahtarlar</td>
      <td>Sabit uzunluklu</td>
      <td>Değişken uzunluklu</td>
    </tr>
    <tr>
      <td>Temel yapı</td>
      <td>Yinelemeli geçiş</td>
      <td>Özyinelemeli bölme</td>
    </tr>
    <tr>
      <td>Güçlü yanı</td>
      <td>Basit ve öngörülebilir</td>
      <td>Gereksiz karakterleri atlayabilir</td>
    </tr>
    <tr>
      <td>Zayıf yanı</td>
      <td>Her karakteri işler</td>
      <td>Küçük gruplarda ek yük oluşturur</td>
    </tr>
  </tbody>
</table>

<h2 id="ne-zaman-daha-hızlıdır">Ne Zaman Daha Hızlıdır?</h2>

<p>Karşılaştırmalı sıralama yaklaşık $N \log N$ adet karar verir; üstelik ortak ön eke sahip dizgilerde aynı karakterleri defalarca okuyabilir. LSD ve MSD ise alfabe küçükken karakterleri kovalar gibi doğrudan kutulara dağıtır. Özellikle $R$ sabit ve anahtar uzunluğu sınırlıysa doğrusal davranışa yaklaşırlar.</p>

<p>Bununla birlikte Unicode gibi çok büyük alfabelerde doğrudan devasa sayım dizileri kullanmak bellek israfına dönüşebilir. Küçük veri kümelerinde de Python’ın yerleşik <code class="language-plaintext highlighter-rouge">sorted</code> fonksiyonu, düşük sabit maliyetleri sayesinde daha hızlı olabilir. Kısacası LSD düzenli veri için güvenilir bir maratoncu, MSD ise ortak önekleri ustaca eleyen çevik bir sprinterdir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="algoritma" /><category term="sıralama" /><category term="lsd" /><category term="msd" /><category term="dizgi" /><category term="python" /><summary type="html"><![CDATA[Bir sözlükteki milyonlarca kelimeyi sıralamanız gerektiğini düşünün. Klasik algoritmalar kelimeleri tekrar tekrar karşılaştırırken LSD ve MSD, karakterleri doğrudan anahtar olarak kullanır. Böylece “hangisi küçük?” sorusunu sürekli sormak yerine karakterlerin dağılımından yararlanırlar. Sonuç, uygun koşullarda karşılaştırmalı sıralamalardan belirgin biçimde daha hızlı çalışan bir yaklaşımdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dizgi-siralamada-hizli-55.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dizgi-siralamada-hizli-55.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Josephus Problemi: Dairede Kim, Ne Zaman Elenecek?</title><link href="https://program.sonsuz.us/posts/josephus-problemi-dairede-kim-ne-zaman-elenecek/" rel="alternate" type="text/html" title="Josephus Problemi: Dairede Kim, Ne Zaman Elenecek?" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/josephus-problemi-dairede-kim-ne-zaman-elenecek</id><content type="html" xml:base="https://program.sonsuz.us/posts/josephus-problemi-dairede-kim-ne-zaman-elenecek/"><![CDATA[<p>Bir grup insanın daire şeklinde dizildiğini, belirli aralıklarla bir kişinin elendiğini ve bu işlemin yalnızca tek kişi kalana kadar sürdüğünü düşünün. Kulağa biraz acımasız bir sandalye kapmaca oyunu gibi gelen <strong>Josephus Problemi</strong>, döngüsel yapıları, indeks hesaplarını ve algoritmik düşünmeyi öğrenmek için kullanılan klasik bir bilgisayar bilimi problemidir.</p>

<p><img src="/img/josephus-problemi-dairede-42.svg" alt="josephus-problemi-dairede-42" /></p>

<p>``</p>

<h2 id="problemin-kuralları">Problemin kuralları</h2>

<p>Dairede $n$ kişi bulunsun. Saymaya birinci kişiden başlayalım ve her $k$ adımda ulaşılan kişiyi eleyelim. Elenen kişinin hemen yanındaki kişiyle saymaya yeniden devam edelim. Amaç iki farklı sonucu hesaplamak olabilir:</p>

<ol>
  <li>Kişilerin elenme sırası,</li>
  <li>Oyunda hayatta kalan son kişi.</li>
</ol>

<p>Örneğin $n=7$ ve $k=3$ olsun. Kişiler <code class="language-plaintext highlighter-rouge">1, 2, 3, 4, 5, 6, 7</code> biçiminde numaralandırılır. İlk elenen kişi 3, sonraki kişi 6 olur. Dairenin sonuna gelindiğinde sayma başa döner.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Tur</th>
      <th>Dairede kalanlar</th>
      <th style="text-align: right">Elenen kişi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>1, 2, 4, 5, 6, 7</td>
      <td style="text-align: right">3</td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>1, 2, 4, 5, 7</td>
      <td style="text-align: right">6</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>1, 2, 4, 5</td>
      <td style="text-align: right">2</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>1, 4, 5</td>
      <td style="text-align: right">7</td>
    </tr>
    <tr>
      <td style="text-align: right">5</td>
      <td>1, 4</td>
      <td style="text-align: right">5</td>
    </tr>
    <tr>
      <td style="text-align: right">6</td>
      <td>4</td>
      <td style="text-align: right">1</td>
    </tr>
  </tbody>
</table>

<p>Böylece elenme sırası $[3,6,2,7,5,1]$, kazanan ise 4 olur.</p>

<h2 id="matematiksel-düşünce">Matematiksel düşünce</h2>

<p>Yalnızca kazananı arıyorsak problemi daha küçük problemlere indirebiliriz. Sıfır tabanlı indeks kullanan Josephus bağıntısı şöyledir:</p>

\[J(1,k)=0\]

\[J(n,k)=(J(n-1,k)+k) \bmod n\]

<p>Buradaki mod işlemi, dairenin sonundan sonra tekrar başa dönmemizi sağlar. İnsanları 1’den başlayarak numaralandırmak istediğimiz için nihai sonuca 1 ekleriz:</p>

\[\text{kazanan}=J(n,k)+1\]

<p>Bu yaklaşım $O(n)$ zamanda ve $O(1)$ ek bellekte çalışır. Ancak yalnızca kazananı verir; bütün elenme sırasını öğrenmek için daireyi ayrıca simüle etmeliyiz.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Ürettiği sonuç</th>
      <th style="text-align: right">Zaman</th>
      <th style="text-align: right">Ek bellek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Matematiksel bağıntı</td>
      <td>Son kalan kişi</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(1)$</td>
    </tr>
    <tr>
      <td>Kuyruk simülasyonu</td>
      <td>Tüm elenme sırası</td>
      <td style="text-align: right">Uygulamaya bağlı</td>
      <td style="text-align: right">$O(n)$</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-daireyi-simüle-etmek">Python ile daireyi simüle etmek</h2>

<p>Python’daki <code class="language-plaintext highlighter-rouge">deque</code>, iki uçtan hızlı ekleme ve çıkarma yapabilen bir kuyruktur. <code class="language-plaintext highlighter-rouge">rotate</code> metodu sayesinde sıradaki kişiyi kuyruğun başına taşıyabiliriz.</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">josephus_sirasi</span><span class="p">(</span><span class="n">kisi_sayisi</span><span class="p">,</span> <span class="n">adim</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">kisi_sayisi</span> <span class="o">&lt;</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">adim</span> <span class="o">&lt;</span> <span class="mi">1</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">Kişi sayısı ve adım pozitif olmalıdır.</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">daire</span> <span class="o">=</span> <span class="nf">deque</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">kisi_sayisi</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="n">elenenler</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">while</span> <span class="nf">len</span><span class="p">(</span><span class="n">daire</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="c1"># İlk kişi zaten birinci sayıldığı için k-1 konum ilerliyoruz.
</span>        <span class="n">daire</span><span class="p">.</span><span class="nf">rotate</span><span class="p">(</span><span class="o">-</span><span class="p">(</span><span class="n">adim</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
        <span class="n">elenenler</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">daire</span><span class="p">.</span><span class="nf">popleft</span><span class="p">())</span>

    <span class="k">return</span> <span class="n">elenenler</span><span class="p">,</span> <span class="n">daire</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>


<span class="n">elenenler</span><span class="p">,</span> <span class="n">kazanan</span> <span class="o">=</span> <span class="nf">josephus_sirasi</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Elenenler:</span><span class="sh">"</span><span class="p">,</span> <span class="n">elenenler</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Kazanan:</span><span class="sh">"</span><span class="p">,</span> <span class="n">kazanan</span><span class="p">)</span>
</code></pre></div></div>

<p>Programın çıktısı şöyledir:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Elenenler: [3, 6, 2, 7, 5, 1]
Kazanan: 4
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">rotate(-(adim - 1))</code> işlemi kuyruğu sola döndürür. Böylece elenecek kişi başa gelir; <code class="language-plaintext highlighter-rouge">popleft()</code> da onu daireden çıkarır. Negatif döndürme miktarı büyük olsa bile <code class="language-plaintext highlighter-rouge">deque</code>, döngüsel davranışı korur.</p>

<h2 id="yalnızca-kazananı-bulmak">Yalnızca kazananı bulmak</h2>

<p>Büyük girişlerde elenme listesini saklamak istemiyorsak bağıntıyı döngüyle uygulayabiliriz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">josephus_kazanan</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
    <span class="n">konum</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">mevcut_boyut</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">2</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">konum</span> <span class="o">=</span> <span class="p">(</span><span class="n">konum</span> <span class="o">+</span> <span class="n">k</span><span class="p">)</span> <span class="o">%</span> <span class="n">mevcut_boyut</span>
    <span class="k">return</span> <span class="n">konum</span> <span class="o">+</span> <span class="mi">1</span>
</code></pre></div></div>

<p>Josephus Problemi küçük bir oyun gibi görünse de modüler aritmetik, kuyruklar, yinelemeli bağıntılar ve performans karşılaştırmaları için güçlü bir örnektir. Adım değerini veya başlangıç kişisini değiştirerek farklı senaryolar üretmek, algoritmanın döngüsel mantığını iyice pekiştirir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="josephus problemi" /><category term="python" /><category term="algoritma" /><category term="veri yapıları" /><category term="matematik" /><category term="simülasyon" /><summary type="html"><![CDATA[Bir grup insanın daire şeklinde dizildiğini, belirli aralıklarla bir kişinin elendiğini ve bu işlemin yalnızca tek kişi kalana kadar sürdüğünü düşünün. Kulağa biraz acımasız bir sandalye kapmaca oyunu gibi gelen Josephus Problemi, döngüsel yapıları, indeks hesaplarını ve algoritmik düşünmeyi öğrenmek için kullanılan klasik bir bilgisayar bilimi problemidir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/josephus-problemi-dairede-42.png" /><media:content medium="image" url="https://program.sonsuz.us/img/josephus-problemi-dairede-42.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Kosaraju-Sharir Algoritması: Yönlü Graflarda Güçlü Bağlı Bileşenleri Bulmak</title><link href="https://program.sonsuz.us/posts/kosaraju-sharir-algoritmasi-yonlu-graflarda-guclu-bagli-bilesenleri-bulmak/" rel="alternate" type="text/html" title="Kosaraju-Sharir Algoritması: Yönlü Graflarda Güçlü Bağlı Bileşenleri Bulmak" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/kosaraju-sharir-algoritmasi-yonlu-graflarda-guclu-bagli-bilesenleri-bulmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/kosaraju-sharir-algoritmasi-yonlu-graflarda-guclu-bagli-bilesenleri-bulmak/"><![CDATA[<p><img src="/img/kosaraju-sharir-algoritmasi-37.svg" alt="kosaraju-sharir-algoritmasi-37" /></p>

<p>Bir sosyal ağda Ayşe, Berk’in paylaşımlarına; Berk, Ceren’in paylaşımlarına; Ceren de Ayşe’nin paylaşımlarına ulaşabiliyorsa bu üçlü kapalı bir iletişim bölgesi oluşturur. Yönlü graflarda bu tür karşılıklı erişilebilir düğüm gruplarına <strong>güçlü bağlı bileşen</strong> denir. Kosaraju-Sharir algoritması, yalnızca iki derinlik öncelikli arama yaparak bu gizli toplulukları ortaya çıkarır.
``</p>

<h2 id="güçlü-bağlılık-nedir">Güçlü bağlılık nedir?</h2>

<p>Bir yönlü grafı $G=(V,E)$ ile gösterelim. $u$ düğümünden $v$ düğümüne yönlü bir yol varsa bunu $u \rightsquigarrow v$ biçiminde yazabiliriz. İki düğümün aynı güçlü bağlı bileşende bulunması için şu koşul sağlanmalıdır:</p>

\[u \sim v \iff (u \rightsquigarrow v) \land (v \rightsquigarrow u)\]

<p>Yani yalnızca ileri gitmek yetmez; geri dönebilmek de gerekir. Bu ilişki dönüşlü, simetrik ve geçişli olduğundan düğümleri birbirinden ayrık sınıflara böler.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Aranan erişim</th>
      <th>Yönler önemli mi?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bağlı bileşen</td>
      <td>Düğümler arasında bir yol</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Zayıf bağlı bileşen</td>
      <td>Kenar yönleri kaldırılınca yol</td>
      <td>Kısmen</td>
    </tr>
    <tr>
      <td>Güçlü bağlı bileşen</td>
      <td>Her iki yönde de yol</td>
      <td>Evet</td>
    </tr>
  </tbody>
</table>

<p>Her düğüm tek başına da güçlü bağlı sayılır. Ancak algoritmanın asıl eğlenceli kısmı, döngüler ve karmaşık bağlantılar arasındaki daha büyük bileşenleri bulmasıdır.</p>

<h2 id="algoritmanın-temel-fikri">Algoritmanın temel fikri</h2>

<p>Kosaraju-Sharir üç aşamada çalışır:</p>

<ol>
  <li>Orijinal grafta DFS yap ve düğümleri <strong>bitiş zamanlarına</strong> göre kaydet.</li>
  <li>Bütün kenarları ters çevirerek $G^T$ transpoz grafını oluştur.</li>
  <li>Düğümleri azalan bitiş zamanı sırasıyla ele alıp $G^T$ üzerinde yeniden DFS yap.</li>
</ol>

<p>İkinci turdaki her DFS ağacı tam olarak bir güçlü bağlı bileşen verir. İlk arama, hangi bileşenin önce ziyaret edilmesi gerektiğini belirleyen bir pusula gibidir.</p>

<p>Bir güçlü bağlı bileşeni tek bir süper düğüme sıkıştırırsak ortaya döngüsüz bir <strong>yoğunlaşma grafı</strong> çıkar. Bu graf bir DAG’dir. İlk DFS’nin bitiş sırası, ikinci geçişte başka bileşenlere yanlışlıkla taşmamızı önleyecek bir sıralama üretir. Kenarlar ters çevrilince bileşenlerin içindeki karşılıklı erişim korunur, bileşenler arasındaki geçiş yönleri ise değişir.</p>

<h2 id="python-ile-uygulama">Python ile uygulama</h2>

<p>Aşağıdaki kod, komşuluk listesiyle verilen bir graftaki bileşenleri 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">kosaraju</span><span class="p">(</span><span class="n">graph</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">finish_order</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">first_dfs</span><span class="p">(</span><span class="n">node</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">node</span><span class="p">)</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="nf">first_dfs</span><span class="p">(</span><span class="n">neighbor</span><span class="p">)</span>
        <span class="n">finish_order</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">node</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="k">if</span> <span class="n">node</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="nf">first_dfs</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>

    <span class="n">transpose</span> <span class="o">=</span> <span class="p">{</span><span class="n">node</span><span class="p">:</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="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">neighbors</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">.</span><span class="nf">items</span><span class="p">():</span>
        <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">:</span>
            <span class="n">transpose</span><span class="p">[</span><span class="n">neighbor</span><span class="p">].</span><span class="nf">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>

    <span class="n">visited</span><span class="p">.</span><span class="nf">clear</span><span class="p">()</span>
    <span class="n">components</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">second_dfs</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">component</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">node</span><span class="p">)</span>
        <span class="n">component</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">transpose</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="nf">second_dfs</span><span class="p">(</span><span class="n">neighbor</span><span class="p">,</span> <span class="n">component</span><span class="p">)</span>

    <span class="k">while</span> <span class="n">finish_order</span><span class="p">:</span>
        <span class="n">node</span> <span class="o">=</span> <span class="n">finish_order</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">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="n">component</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="nf">second_dfs</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">component</span><span class="p">)</span>
            <span class="n">components</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">component</span><span class="p">)</span>

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

<p>İlk <code class="language-plaintext highlighter-rouge">first_dfs</code>, bir düğümü ancak bütün komşuları tamamlandıktan sonra listeye ekler. Listenin sonundan eleman almak azalan bitiş sırasını sağlar. <code class="language-plaintext highlighter-rouge">second_dfs</code> ise transpoz grafta ulaşabildiği düğümleri aynı bileşende toplar.</p>

<h2 id="karmaşıklık-ve-kullanım-alanları">Karmaşıklık ve kullanım alanları</h2>

<p>Her düğüm ve kenar sabit sayıda işlendiği için zaman karmaşıklığı</p>

\[T(V,E)=O(\vert V\vert +\vert E\vert )\]

<p>olur. Graf, transpoz yapı, ziyaret kümeleri ve DFS yığını için gereken bellek de $O(\vert V\vert +\vert E\vert )$ düzeyindedir.</p>

<p>Kosaraju-Sharir; sosyal ağ toplulukları, paket bağımlılık döngüleri, web bağlantıları, çağrı grafları ve durum makinelerinin analizinde kullanılabilir. İki DFS ile koskoca bir yönlü grafın içindeki karşılıklı ulaşılabilir adaları bulmak, algoritmanın hem zarif hem de pratik olmasının temel nedenidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="graf teorisi" /><category term="kosaraju" /><category term="güçlü bağlı bileşen" /><category term="dfs" /><category term="algoritma" /><category term="python" /><summary type="html"><![CDATA[Bir sosyal ağda Ayşe, Berk’in paylaşımlarına; Berk, Ceren’in paylaşımlarına; Ceren de Ayşe’nin paylaşımlarına ulaşabiliyorsa bu üçlü kapalı bir iletişim bölgesi oluşturur. Yönlü graflarda bu tür karşılıklı erişilebilir düğüm gruplarına güçlü bağlı bileşen denir. Kosaraju-Sharir algoritması, yalnızca iki derinlik öncelikli arama yaparak bu gizli toplulukları ortaya çıkarır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/kosaraju-sharir-algoritmasi-37.png" /><media:content medium="image" url="https://program.sonsuz.us/img/kosaraju-sharir-algoritmasi-37.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>