<?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-14T12:05:46+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">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">Quickselect ile Ortanca ve k. En Küçük Elemanı Bulma</title><link href="https://program.sonsuz.us/posts/quickselect-ile-ortanca-ve-k-en-kucuk-elemani-bulma/" rel="alternate" type="text/html" title="Quickselect ile Ortanca ve k. En Küçük Elemanı Bulma" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/quickselect-ile-ortanca-ve-k-en-kucuk-elemani-bulma</id><content type="html" xml:base="https://program.sonsuz.us/posts/quickselect-ile-ortanca-ve-k-en-kucuk-elemani-bulma/"><![CDATA[<p>Bir dizinin ortancasını bulmak için akla gelen ilk yöntem diziyi sıralamaktır. Ancak yalnızca belirli bir sıradaki elemanla ilgileniyorsak bütün diziyi sıralamak, tek bir kitabı bulmak için kütüphanenin tamamını yeniden dizmeye benzer. Quickselect algoritması, Quick Sort’un bölümleme fikrini kullanarak diziyi tamamen sıralamadan ortalama $O(n)$ zamanda k. en küçük elemanı bulur.
``</p>

<h2 id="sıra-istatistiği-nedir">Sıra istatistiği nedir?</h2>

<p>Bir dizinin küçükten büyüğe sıralanmış hâlindeki belirli konumlara <strong>sıra istatistikleri</strong> denir. En küçük eleman birinci, en büyük eleman n. sıra istatistiğidir. Ortanca da merkezi sıra istatistiğidir.</p>

<p>$n$ tekse ortancanın sıfır tabanlı indeksi şöyledir:</p>

\[k = \lfloor n / 2 \rfloor\]

<p>$n$ çiftse istatistiksel ortanca, ortadaki iki elemanın aritmetik ortalamasıdır:</p>

\[\text{medyan} = \frac{x_{n/2-1} + x_{n/2}}{2}\]

<p>Burada önemli bir ayrıntı bulunur: Günlük dilde “k. en küçük” ifadesinde saymaya 1’den başlanır; Python dizilerinde ise indeksler 0’dan başlar. Dolayısıyla kullanıcı 3. en küçük elemanı istediğinde algoritmaya $k=2$ verilmelidir.</p>

<table>
  <thead>
    <tr>
      <th>İstenen değer</th>
      <th style="text-align: right">Sıralanmış dizideki konum</th>
      <th style="text-align: right">Sıfır tabanlı indeks</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>En küçük</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right">0</td>
    </tr>
    <tr>
      <td>3. en küçük</td>
      <td style="text-align: right">3</td>
      <td style="text-align: right">2</td>
    </tr>
    <tr>
      <td>En büyük</td>
      <td style="text-align: right">n</td>
      <td style="text-align: right">n-1</td>
    </tr>
    <tr>
      <td>Tek uzunlukta ortanca</td>
      <td style="text-align: right">$(n+1)/2$</td>
      <td style="text-align: right">$\lfloor n/2 \rfloor$</td>
    </tr>
  </tbody>
</table>

<h2 id="quickselect-nasıl-çalışır">Quickselect nasıl çalışır?</h2>

<p>Algoritma bir <strong>pivot</strong> seçer ve diziyi pivot değerinden küçük, eşit ve büyük elemanlar olarak düşünür. Bölümleme tamamlandığında pivot nihai sıralı konumuna yerleşmiş olur. Pivotun indeksi aranan $k$ indeksine eşitse işlem biter. Pivot fazla soldaysa yalnızca sağ bölümde, fazla sağdaysa yalnızca sol bölümde arama sürdürülür.</p>

<p>Quick Sort iki tarafı da işlerken Quickselect sadece gerekli tarafı işler. Hız kazancı tam olarak buradan gelir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Tam sıralama</th>
      <th>Quickselect</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ortalama süre</td>
      <td>$O(n \log n)$</td>
      <td>$O(n)$</td>
    </tr>
    <tr>
      <td>En kötü süre</td>
      <td>Genellikle $O(n \log n)$</td>
      <td>$O(n^2)$</td>
    </tr>
    <tr>
      <td>Tüm sıralı dizi</td>
      <td>Evet</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Tek sıra istatistiği</td>
      <td>Gereğinden pahalı olabilir</td>
      <td>Çok uygundur</td>
    </tr>
  </tbody>
</table>

<h2 id="python-uygulaması">Python uygulaması</h2>

<p>Aşağıdaki uygulama, kötü pivot seçimlerinin olasılığını azaltmak için rastgele bir elemanı sona taşıyor. Ardından Lomuto bölümleme yöntemiyle pivotun doğru indeksini buluyor.</p>

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

<span class="k">def</span> <span class="nf">partition</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">left</span><span class="p">,</span> <span class="n">right</span><span class="p">):</span>
    <span class="n">pivot_index</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">randint</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">right</span><span class="p">)</span>
    <span class="n">values</span><span class="p">[</span><span class="n">pivot_index</span><span class="p">],</span> <span class="n">values</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="n">right</span><span class="p">],</span> <span class="n">values</span><span class="p">[</span><span class="n">pivot_index</span><span class="p">]</span>
    <span class="n">pivot</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="n">right</span><span class="p">]</span>

    <span class="n">store</span> <span class="o">=</span> <span class="n">left</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">left</span><span class="p">,</span> <span class="n">right</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">values</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">pivot</span><span class="p">:</span>
            <span class="n">values</span><span class="p">[</span><span class="n">store</span><span class="p">],</span> <span class="n">values</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="n">index</span><span class="p">],</span> <span class="n">values</span><span class="p">[</span><span class="n">store</span><span class="p">]</span>
            <span class="n">store</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="n">values</span><span class="p">[</span><span class="n">store</span><span class="p">],</span> <span class="n">values</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="n">right</span><span class="p">],</span> <span class="n">values</span><span class="p">[</span><span class="n">store</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">store</span>


<span class="k">def</span> <span class="nf">quickselect</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">values</span><span class="p">):</span>
        <span class="k">raise</span> <span class="nc">IndexError</span><span class="p">(</span><span class="sh">"</span><span class="s">k geçerli bir indeks olmalıdır</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;=</span> <span class="n">right</span><span class="p">:</span>
        <span class="n">pivot_index</span> <span class="o">=</span> <span class="nf">partition</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">left</span><span class="p">,</span> <span class="n">right</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">pivot_index</span> <span class="o">==</span> <span class="n">k</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">values</span><span class="p">[</span><span class="n">pivot_index</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">pivot_index</span> <span class="o">&lt;</span> <span class="n">k</span><span class="p">:</span>
            <span class="n">left</span> <span class="o">=</span> <span class="n">pivot_index</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">right</span> <span class="o">=</span> <span class="n">pivot_index</span> <span class="o">-</span> <span class="mi">1</span>
</code></pre></div></div>

<p>Örneğin <code class="language-plaintext highlighter-rouge">quickselect([9, 2, 7, 1, 5], 2)</code> çağrısı <code class="language-plaintext highlighter-rouge">5</code> döndürür. Fonksiyon diziyi yerinde değiştirdiği için özgün sıralama korunacaksa <code class="language-plaintext highlighter-rouge">quickselect(values.copy(), k)</code> kullanılmalıdır.</p>

<h2 id="karmaşıklığın-arkasındaki-fikir">Karmaşıklığın arkasındaki fikir</h2>

<p>Dengeli pivotlar seçildiğinde incelenen eleman sayısı yaklaşık olarak şu seriyi oluşturur:</p>

\[T(n) = n + \frac{n}{2} + \frac{n}{4} + \cdots &lt; 2n\]

<p>Bu nedenle beklenen zaman karmaşıklığı $O(n)$ olur. Buna karşılık pivot sürekli en küçük veya en büyük eleman seçilirse $n+(n-1)+\cdots+1$ işlem oluşur ve sonuç $O(n^2)$ seviyesine çıkar. Rastgele pivot pratikte bu talihsiz senaryoyu oldukça düşük olasılıklı hâle getirir.</p>

<p>Quickselect; büyük veri kümelerinde yüzdelik dilim, ortanca, liderlik sırası ve eşik değeri hesaplamak için güçlü bir araçtır. Tüm sıralamaya ihtiyacınız yoksa algoritmik valizinize koymaya kesinlikle değer.</p>

<p><img src="/img/quickselect-ile-ortanca-88.svg" alt="quickselect-ile-ortanca-88" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="quickselect" /><category term="algoritma" /><category term="sıra-istatistikleri" /><category term="python" /><category term="ortanca" /><category term="böl-ve-yönet" /><summary type="html"><![CDATA[Bir dizinin ortancasını bulmak için akla gelen ilk yöntem diziyi sıralamaktır. Ancak yalnızca belirli bir sıradaki elemanla ilgileniyorsak bütün diziyi sıralamak, tek bir kitabı bulmak için kütüphanenin tamamını yeniden dizmeye benzer. Quickselect algoritması, Quick Sort’un bölümleme fikrini kullanarak diziyi tamamen sıralamadan ortalama $O(n)$ zamanda k. en küçük elemanı bulur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/quickselect-ile-ortanca-88.png" /><media:content medium="image" url="https://program.sonsuz.us/img/quickselect-ile-ortanca-88.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Seyrek Matris-Vektör Çarpımı: Sıfırları Taşımadan Hız Kazanmak</title><link href="https://program.sonsuz.us/posts/seyrek-matris-vektor-carpimi-sifirlari-tasimadan-hiz-kazanmak/" rel="alternate" type="text/html" title="Seyrek Matris-Vektör Çarpımı: Sıfırları Taşımadan Hız Kazanmak" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/seyrek-matris-vektor-carpimi-sifirlari-tasimadan-hiz-kazanmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/seyrek-matris-vektor-carpimi-sifirlari-tasimadan-hiz-kazanmak/"><![CDATA[<p>Devasa bir matristeki elemanların büyük bölümü sıfırsa, bu sıfırları bellekte saklamak biraz boş koltuklarla dolu bir otobüsü şehir turuna çıkarmaya benzer. Seyrek matris gösterimleri yalnızca anlamlı değerleri ve konumlarını saklayarak hem bellek tüketimini hem de matris-vektör çarpımının işlem maliyetini azaltır.</p>

<p>``</p>

<h2 id="matris-neden-seyrek-olur">Matris neden “seyrek” olur?</h2>

<p>Graf bağlantı matrisleri, öneri sistemleri, sonlu eleman analizleri ve doğal dil işleme modelleri çoğunlukla seyrek veri üretir. Örneğin bir sosyal ağda milyonlarca kullanıcı bulunabilir; ancak her kullanıcı yalnızca birkaç yüz kişiyle bağlantılıdır.</p>

<p>Bir $A \in \mathbb{R}^{m \times n}$ matrisi ile $x \in \mathbb{R}^{n}$ vektörünün çarpımı şöyledir:</p>

\[y_i = \sum_{j=1}^{n} A_{ij}x_j\]

<p>Yoğun gösterimde her satırdaki bütün sütunlar dolaşılır. Böylece zaman karmaşıklığı $O(mn)$ olur. Oysa yalnızca sıfır olmayan elemanları işlersek maliyet yaklaşık olarak</p>

\[O(\operatorname{nnz}(A))\]

<p>seviyesine iner. Buradaki $\operatorname{nnz}(A)$, matrisin sıfır olmayan eleman sayısıdır.</p>

<h2 id="popüler-gösterim-biçimleri">Popüler gösterim biçimleri</h2>

<table>
  <thead>
    <tr>
      <th>Biçim</th>
      <th>Saklanan bilgiler</th>
      <th>Güçlü tarafı</th>
      <th>Zayıf tarafı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>COO</td>
      <td>Satır, sütun ve değer üçlüleri</td>
      <td>Oluşturması ve güncellemesi kolaydır</td>
      <td>Tekrarlı indisler ve ek bellek maliyeti olabilir</td>
    </tr>
    <tr>
      <td>CSR</td>
      <td>Değerler, sütun indisleri, satır başlangıçları</td>
      <td>Satır tabanlı çarpım çok hızlıdır</td>
      <td>Sütun işlemleri ve ekleme pahalıdır</td>
    </tr>
    <tr>
      <td>CSC</td>
      <td>Değerler, satır indisleri, sütun başlangıçları</td>
      <td>Sütun tabanlı işlemler verimlidir</td>
      <td>Satır erişimi daha maliyetlidir</td>
    </tr>
    <tr>
      <td>DOK</td>
      <td>Koordinatları anahtar olarak kullanan sözlük</td>
      <td>Dinamik eleman eklemek rahattır</td>
      <td>Sayısal hesaplamalarda yavaştır</td>
    </tr>
  </tbody>
</table>

<p>Matris-vektör çarpımı, yani <strong>SpMV</strong>, çoğunlukla satırlar üzerinden ilerlediği için CSR biçimi yaygın bir tercihtir.</p>

<h2 id="csr-mantığını-parçalarına-ayıralım">CSR mantığını parçalarına ayıralım</h2>

<p>Aşağıdaki matrisi düşünelim:</p>

\[A = \begin{bmatrix}
5 &amp; 0 &amp; 0 &amp; 2 \\
0 &amp; 3 &amp; 0 &amp; 0 \\
1 &amp; 0 &amp; 4 &amp; 0
\end{bmatrix}\]

<p>CSR gösteriminde üç dizi kullanılır:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">values = [5, 2, 3, 1, 4]</code></li>
  <li><code class="language-plaintext highlighter-rouge">col_indices = [0, 3, 1, 0, 2]</code></li>
  <li><code class="language-plaintext highlighter-rouge">row_ptr = [0, 2, 3, 5]</code></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">row_ptr</code>, her satırın <code class="language-plaintext highlighter-rouge">values</code> dizisinde nerede başlayıp bittiğini belirtir. Böylece algoritma sıfırların bulunduğu hücrelere hiç uğramaz.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">csr_matvec</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">col_indices</span><span class="p">,</span> <span class="n">row_ptr</span><span class="p">,</span> <span class="n">vector</span><span class="p">):</span>
    <span class="n">rows</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">row_ptr</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="n">result</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">rows</span>

    <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">rows</span><span class="p">):</span>
        <span class="n">start</span> <span class="o">=</span> <span class="n">row_ptr</span><span class="p">[</span><span class="n">row</span><span class="p">]</span>
        <span class="n">end</span> <span class="o">=</span> <span class="n">row_ptr</span><span class="p">[</span><span class="n">row</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>

        <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">):</span>
            <span class="n">column</span> <span class="o">=</span> <span class="n">col_indices</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
            <span class="n">result</span><span class="p">[</span><span class="n">row</span><span class="p">]</span> <span class="o">+=</span> <span class="n">values</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">vector</span><span class="p">[</span><span class="n">column</span><span class="p">]</span>

    <span class="k">return</span> <span class="n">result</span>

<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="n">columns</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</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="mi">2</span><span class="p">]</span>
<span class="n">row_ptr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">x</span> <span class="o">=</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="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">csr_matvec</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">columns</span><span class="p">,</span> <span class="n">row_ptr</span><span class="p">,</span> <span class="n">x</span><span class="p">))</span>
<span class="c1"># [13.0, 6.0, 13.0]
</span></code></pre></div></div>

<p>Kod, her satır için yalnızca ilgili değer aralığını gezer. Örneğin ilk sonuç $5 \cdot 1 + 2 \cdot 4 = 13$ şeklinde hesaplanır.</p>

<h2 id="bellek-kazancı-gerçekten-büyük-mü">Bellek kazancı gerçekten büyük mü?</h2>

<p>Bir $10{,}000 \times 10{,}000$ matris, 64 bit kayan noktalı sayılarla yoğun biçimde yaklaşık 800 MB yer kaplar. Matrisin yalnızca yüzde biri doluysa bir milyon anlamlı değer vardır. CSR biçiminde değerler ile 32 bit indisler kabaca 12 MB, satır işaretçileri ise yaklaşık 40 KB gerektirir. Ek yapılar hesaba katılsa bile fark dramatiktir.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th style="text-align: right">Yoğun matris</th>
      <th style="text-align: right">Seyrek CSR</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bellek kullanımı</td>
      <td style="text-align: right">Tüm hücrelerle orantılı</td>
      <td style="text-align: right">Sıfır olmayanlarla orantılı</td>
    </tr>
    <tr>
      <td>Eleman ekleme</td>
      <td style="text-align: right">Kolay</td>
      <td style="text-align: right">Genellikle pahalı</td>
    </tr>
    <tr>
      <td>SpMV performansı</td>
      <td style="text-align: right">Çok sayıda gereksiz çarpım</td>
      <td style="text-align: right">Yalnızca anlamlı çarpımlar</td>
    </tr>
    <tr>
      <td>Önbellek davranışı</td>
      <td style="text-align: right">Düzenli erişim</td>
      <td style="text-align: right">İndisler nedeniyle düzensiz olabilir</td>
    </tr>
  </tbody>
</table>

<p>Seyrek yapı her zaman otomatik zafer değildir. Matris yeterince doluysa indislerin bellek maliyeti avantajı azaltabilir. Ayrıca SpMV çoğu sistemde işlemciden çok bellek bant genişliğiyle sınırlıdır. Bu nedenle doğru format; matrisin doluluk oranına, erişim yönüne ve güncellenme sıklığına göre seçilmelidir. Kısacası hızın sırrı, sıfırlarla daha hızlı çarpışmak değil, onları tamamen görmezden gelmektir.</p>

<p><img src="/img/seyrek-matris-vektor-16.svg" alt="seyrek-matris-vektor-16" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="seyrek-matris" /><category term="lineer-cebir" /><category term="python" /><category term="algoritma" /><category term="yüksek-performans" /><category term="bellek-optimizasyonu" /><summary type="html"><![CDATA[Devasa bir matristeki elemanların büyük bölümü sıfırsa, bu sıfırları bellekte saklamak biraz boş koltuklarla dolu bir otobüsü şehir turuna çıkarmaya benzer. Seyrek matris gösterimleri yalnızca anlamlı değerleri ve konumlarını saklayarak hem bellek tüketimini hem de matris-vektör çarpımının işlem maliyetini azaltır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/seyrek-matris-vektor-16.png" /><media:content medium="image" url="https://program.sonsuz.us/img/seyrek-matris-vektor-16.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Sıralama Algoritmalarında Kararlılık: Eşitler Arasında Düzeni Korumak</title><link href="https://program.sonsuz.us/posts/siralama-algoritmalarinda-kararlilik-esitler-arasinda-duzeni-korumak/" rel="alternate" type="text/html" title="Sıralama Algoritmalarında Kararlılık: Eşitler Arasında Düzeni Korumak" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/siralama-algoritmalarinda-kararlilik-esitler-arasinda-duzeni-korumak</id><content type="html" xml:base="https://program.sonsuz.us/posts/siralama-algoritmalarinda-kararlilik-esitler-arasinda-duzeni-korumak/"><![CDATA[<p>Bir sıralama algoritması yalnızca elemanları küçükten büyüğe dizmekle kalmaz; bazen eşit kabul edilen elemanların geçmişine de saygı göstermelidir. İşte <strong>kararlılık (stability)</strong>, aynı sıralama anahtarına sahip elemanların başlangıçtaki göreli sırasının korunmasını ifade eder. İlk bakışta küçük bir ayrıntı gibi görünse de çok alanlı kayıtlar, raporlar ve kullanıcı arayüzleri söz konusu olduğunda sonuçları belirgin biçimde etkiler.</p>

<p>``</p>

<h2 id="kararlılık-tam-olarak-nedir">Kararlılık tam olarak nedir?</h2>

<p>Bir dizide $a_i$ ve $a_j$ elemanlarının sıralama anahtarları eşitse ve başlangıçta $a_i$, $a_j$ elemanından önce geliyorsa kararlı algoritma bu ilişkiyi sıralamadan sonra da korur.</p>

<p>Matematiksel olarak koşulu şöyle gösterebiliriz:</p>

\[i &lt; j \land k(a_i)=k(a_j) \Rightarrow p(a_i)&lt;p(a_j)\]

<p>Burada $k(a)$ elemanın sıralama anahtarını, $p(a)$ ise sıralanmış dizideki yeni konumunu temsil eder. Algoritma bu koşulu garanti etmiyorsa <strong>kararsız</strong> olarak adlandırılır. Kararsızlık, sonucun yanlış sıralandığı anlamına gelmez; yalnızca eşit elemanların kendi aralarında yer değiştirebileceğini söyler.</p>

<h2 id="küçük-ama-açıklayıcı-bir-örnek">Küçük ama açıklayıcı bir örnek</h2>

<p>Bir yarışma listesinin geliş sırasıyla kaydedildiğini düşünelim:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Başlangıç sırası</th>
      <th>İsim</th>
      <th style="text-align: right">Puan</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>Ada</td>
      <td style="text-align: right">90</td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>Ece</td>
      <td style="text-align: right">75</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Mert</td>
      <td style="text-align: right">90</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>Can</td>
      <td style="text-align: right">75</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/siralama-algoritmalarinda-kararlilik-74.svg" alt="siralama-algoritmalarinda-kararlilik-74" /></p>

<p>Listeyi puana göre azalan biçimde sıraladığımızda kararlı sonuç şöyledir:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Yeni sıra</th>
      <th>İsim</th>
      <th style="text-align: right">Puan</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>Ada</td>
      <td style="text-align: right">90</td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>Mert</td>
      <td style="text-align: right">90</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Ece</td>
      <td style="text-align: right">75</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>Can</td>
      <td style="text-align: right">75</td>
    </tr>
  </tbody>
</table>

<p>Ada ile Mert eşit puanlıdır ve Ada başlangıçta önce geldiği için yeni listede de öndedir. Benzer şekilde Ece, Can’ın önünde kalmıştır. Kararsız bir algoritma aynı puan sıralamasını üretirken bu ikililerin yerlerini değiştirebilir.</p>

<h2 id="hangi-algoritmalar-kararlıdır">Hangi algoritmalar kararlıdır?</h2>

<p>Algoritmanın klasik uygulanışı dikkate alındığında genel görünüm şöyledir:</p>

<table>
  <thead>
    <tr>
      <th>Algoritma</th>
      <th>Genellikle kararlı mı?</th>
      <th>Temel neden</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bubble Sort</td>
      <td>Evet</td>
      <td>Yalnızca yanlış sıradaki komşuları değiştirir</td>
    </tr>
    <tr>
      <td>Insertion Sort</td>
      <td>Evet</td>
      <td>Eşit elemanı gereksiz yere öne taşımaz</td>
    </tr>
    <tr>
      <td>Merge Sort</td>
      <td>Evet</td>
      <td>Birleştirmede soldaki eşit eleman önce seçilebilir</td>
    </tr>
    <tr>
      <td>Selection Sort</td>
      <td>Hayır</td>
      <td>Uzak eleman değişimleri göreli sırayı bozabilir</td>
    </tr>
    <tr>
      <td>Quick Sort</td>
      <td>Hayır</td>
      <td>Bölümleme sırasında eşitler yer değiştirebilir</td>
    </tr>
    <tr>
      <td>Heap Sort</td>
      <td>Hayır</td>
      <td>Kök ve uzak konum değişimleri düzeni korumaz</td>
    </tr>
  </tbody>
</table>

<p>Bu özellik algoritmanın isminden çok <strong>uygulama biçimine</strong> bağlıdır. Örneğin Merge Sort, eşitlik durumunda sağ taraftaki elemanı önce seçerse kararlılığını kaybedebilir.</p>

<h2 id="kod-üzerinde-kararlı-sıralama">Kod üzerinde kararlı sıralama</h2>

<p>Python’daki <code class="language-plaintext highlighter-rouge">sorted</code> fonksiyonu kararlıdır. Bu sayede kayıtları aşamalı olarak güvenle sıralayabiliriz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">users</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">{</span><span class="sh">'</span><span class="s">name</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="sh">'</span><span class="s">department</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Yazılım</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">age</span><span class="sh">'</span><span class="p">:</span> <span class="mi">28</span><span class="p">},</span>
    <span class="p">{</span><span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Mert</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">department</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Tasarım</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">age</span><span class="sh">'</span><span class="p">:</span> <span class="mi">28</span><span class="p">},</span>
    <span class="p">{</span><span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Ece</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">department</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Yazılım</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">age</span><span class="sh">'</span><span class="p">:</span> <span class="mi">24</span><span class="p">},</span>
<span class="p">]</span>

<span class="c1"># Önce ikincil anahtara göre sıralanır.
</span><span class="n">users</span> <span class="o">=</span> <span class="nf">sorted</span><span class="p">(</span><span class="n">users</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">user</span><span class="p">:</span> <span class="n">user</span><span class="p">[</span><span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">])</span>

<span class="c1"># Kararlılık sayesinde isim sırası eşit bölümlerde korunur.
</span><span class="n">users</span> <span class="o">=</span> <span class="nf">sorted</span><span class="p">(</span><span class="n">users</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">user</span><span class="p">:</span> <span class="n">user</span><span class="p">[</span><span class="sh">'</span><span class="s">department</span><span class="sh">'</span><span class="p">])</span>
</code></pre></div></div>

<p>İkinci sıralama bölümleri düzenlerken aynı bölümdeki kullanıcıların önceden oluşturulmuş isim sırasını bozmaz. Böylece birden fazla ölçüte göre sıralama yapılabilir. Bunun tek çağrılı karşılığı <code class="language-plaintext highlighter-rouge">key=lambda user: (user['department'], user['name'])</code> biçiminde bir demet kullanmaktır.</p>

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

<p>Kararlılık özellikle veritabanı sonuçları, e-ticaret ürün listeleri, günlük kayıtları ve tablo arayüzlerinde önem kazanır. Kullanıcı ürünleri önce tarihe, ardından fiyata göre sıraladığında eşit fiyatlı ürünlerin tarih düzeninin korunmasını bekleyebilir. Düzen rastgele değişirse uygulama hatalı olmasa bile öngörülemez görünür.</p>

<p>Bununla birlikte her problem kararlı algoritma gerektirmez. Elemanlar benzersizse veya yalnızca sayısal nihai sıra önemliyse daha hızlı, daha az bellek kullanan kararsız bir yöntem tercih edilebilir. Doğru seçim; zaman karmaşıklığı, bellek tüketimi ve kararlılık beklentisinin birlikte değerlendirilmesiyle yapılır. Kısacası kararlılık, eşitlerin sıkıcı bir teknik detayı değil, verinin hikâyesini koruyan görünmez bir nezaket kuralıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="sıralama algoritmaları" /><category term="kararlılık" /><category term="algoritma" /><category term="veri yapıları" /><category term="python" /><summary type="html"><![CDATA[Bir sıralama algoritması yalnızca elemanları küçükten büyüğe dizmekle kalmaz; bazen eşit kabul edilen elemanların geçmişine de saygı göstermelidir. İşte kararlılık (stability), aynı sıralama anahtarına sahip elemanların başlangıçtaki göreli sırasının korunmasını ifade eder. İlk bakışta küçük bir ayrıntı gibi görünse de çok alanlı kayıtlar, raporlar ve kullanıcı arayüzleri söz konusu olduğunda sonuçları belirgin biçimde etkiler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/siralama-algoritmalarinda-kararlilik-74.png" /><media:content medium="image" url="https://program.sonsuz.us/img/siralama-algoritmalarinda-kararlilik-74.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Soyut Veri Tipleri: İçeriyi Gizle, Güvenli Arayüzler Tasarla</title><link href="https://program.sonsuz.us/posts/soyut-veri-tipleri-iceriyi-gizle-guvenli-arayuzler-tasarla/" rel="alternate" type="text/html" title="Soyut Veri Tipleri: İçeriyi Gizle, Güvenli Arayüzler Tasarla" /><published>2026-10-14T00:00:00+00:00</published><updated>2026-10-14T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/soyut-veri-tipleri-iceriyi-gizle-guvenli-arayuzler-tasarla</id><content type="html" xml:base="https://program.sonsuz.us/posts/soyut-veri-tipleri-iceriyi-gizle-guvenli-arayuzler-tasarla/"><![CDATA[<p>Bir kahve makinesini kullanmak için içindeki pompanın basıncını veya ısıtıcının devresini bilmemiz gerekmez; düğmeye basar, kahvemizi alırız. Soyut Veri Tipleri de benzer biçimde çalışır: Kullanıcıya <strong>ne yapılabileceğini</strong> gösterirken bunun <strong>nasıl yapıldığını</strong> gizler. Böylece veri yapıları daha güvenli, değiştirilebilir ve anlaşılır hâle gelir.
``</p>
<h2 id="soyut-veri-tipi-nedir">Soyut Veri Tipi nedir?</h2>

<p>Soyut Veri Tipi veya kısaca <strong>ADT (Abstract Data Type)</strong>, bir veri koleksiyonunu yalnızca değerleri ve izin verilen işlemleri üzerinden tanımlar. ADT, doğrudan bir sınıf ya da belirli bir kod parçası değildir; daha çok uygulanması gereken davranışsal bir sözleşmedir.</p>

<p>Bir ADT kabaca şu bileşenlerle ifade edilebilir:</p>

\[ADT = (D, O, A)\]

<p>Burada $D$ olası değerler kümesini, $O$ sunulan işlemleri, $A$ ise bu işlemlerin uyması gereken kuralları belirtir. Örneğin yığın ADT’sinde <code class="language-plaintext highlighter-rouge">push</code>, <code class="language-plaintext highlighter-rouge">pop</code>, <code class="language-plaintext highlighter-rouge">peek</code> ve <code class="language-plaintext highlighter-rouge">isEmpty</code> işlemleri bulunur. Ancak elemanların bir diziyle mi, bağlı listeyle mi tutulduğu sözleşmenin parçası değildir.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Cevapladığı soru</th>
      <th>Yığın örneği</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Arayüz</td>
      <td>Ne yapabilirim?</td>
      <td><code class="language-plaintext highlighter-rouge">push</code>, <code class="language-plaintext highlighter-rouge">pop</code>, <code class="language-plaintext highlighter-rouge">peek</code></td>
    </tr>
    <tr>
      <td>Uygulama</td>
      <td>Nasıl yapılıyor?</td>
      <td>Dizi veya bağlı liste</td>
    </tr>
    <tr>
      <td>Değişmez</td>
      <td>Her zaman ne doğru kalmalı?</td>
      <td>Eleman sayısı negatif olamaz</td>
    </tr>
    <tr>
      <td>İstemci</td>
      <td>ADT’yi kim kullanır?</td>
      <td>Uygulama kodu</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/soyut-veri-tipleri-24.svg" alt="soyut-veri-tipleri-24" /></p>

<h2 id="temsil-bağımsızlığı-ve-kapsülleme">Temsil bağımsızlığı ve kapsülleme</h2>

<p>ADT tasarımının süper gücü <strong>temsil bağımsızlığıdır</strong>. İstemci kodu iç depolama biçimine erişemiyorsa uygulama daha sonra değiştirilebilir. Başlangıçta dizi kullanan bir yığın, performans ihtiyacı nedeniyle bağlı listeye geçirilebilir; arayüz aynı kaldığı sürece kullanıcı bunu fark etmez.</p>

<p>İç veriyi doğrudan dışarı açmak ise değişmezlerin bozulmasına yol açar. Örneğin istemci yığının eleman dizisini temizleyip sayaç değerini değiştirmezse nesne tutarsız hâle gelir. Bu nedenle veri <code class="language-plaintext highlighter-rouge">private</code>, güvenli işlemler ise <code class="language-plaintext highlighter-rouge">public</code> tutulmalıdır.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">interface</span> <span class="nx">Stack</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span> <span class="p">{</span>
  <span class="nf">push</span><span class="p">(</span><span class="na">value</span><span class="p">:</span> <span class="nx">T</span><span class="p">):</span> <span class="k">void</span><span class="p">;</span>
  <span class="nf">pop</span><span class="p">():</span> <span class="nx">T</span><span class="p">;</span>
  <span class="nf">peek</span><span class="p">():</span> <span class="nx">T</span><span class="p">;</span>
  <span class="nf">isEmpty</span><span class="p">():</span> <span class="nx">boolean</span><span class="p">;</span>
  <span class="nf">size</span><span class="p">():</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">ArrayStack</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span> <span class="k">implements</span> <span class="nx">Stack</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span> <span class="p">{</span>
  <span class="k">private</span> <span class="na">items</span><span class="p">:</span> <span class="nx">T</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[];</span>

  <span class="nf">push</span><span class="p">(</span><span class="na">value</span><span class="p">:</span> <span class="nx">T</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="nf">pop</span><span class="p">():</span> <span class="nx">T</span> <span class="p">{</span>
    <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nf">isEmpty</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nc">Error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Boş yığından eleman çıkarılamaz</span><span class="dl">"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nf">pop</span><span class="p">()</span> <span class="kd">as </span><span class="nx">T</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nf">peek</span><span class="p">():</span> <span class="nx">T</span> <span class="p">{</span>
    <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nf">isEmpty</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">throw</span> <span class="k">new</span> <span class="nc">Error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Boş yığının tepesi yoktur</span><span class="dl">"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
  <span class="p">}</span>

  <span class="nf">isEmpty</span><span class="p">():</span> <span class="nx">boolean</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nf">size</span><span class="p">():</span> <span class="kr">number</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> davranış sözleşmesini, <code class="language-plaintext highlighter-rouge">ArrayStack&lt;T&gt;</code> ise dizi tabanlı uygulamayı temsil eder. <code class="language-plaintext highlighter-rouge">items</code> alanının özel olması, istemcinin yığını kuralları atlayarak değiştirmesini engeller.</p>

<h2 id="ön-koşullar-son-koşullar-ve-değişmezler">Ön koşullar, son koşullar ve değişmezler</h2>

<p>Güvenli bir arayüz tasarlanırken her işlem için üç soru sorulabilir:</p>

<ul>
  <li><strong>Ön koşul:</strong> İşlem çağrılmadan önce ne doğru olmalı?</li>
  <li><strong>Son koşul:</strong> İşlem tamamlandığında ne garanti edilir?</li>
  <li><strong>Değişmez:</strong> Nesnenin ömrü boyunca hangi kural korunur?</li>
</ul>

<p>Yığın için <code class="language-plaintext highlighter-rouge">pop</code> işleminin ön koşulu $size &gt; 0$ olabilir. Başarılı işlemden sonra:</p>

\[size_{sonra} = size_{önce} - 1\]

<p>Ayrıca LIFO kuralı gereği son eklenen eleman ilk çıkar. Ön koşul sağlanmadığında sessizce <code class="language-plaintext highlighter-rouge">undefined</code> döndürmek yerine açık bir hata üretmek, hatanın kaynağını görünür kılar.</p>

<table>
  <thead>
    <tr>
      <th>Zayıf tasarım</th>
      <th>Güvenli ADT tasarımı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>İç koleksiyonu dışarı açar</td>
      <td>Kontrollü metotlar sunar</td>
    </tr>
    <tr>
      <td>Belirsiz hata davranışı vardır</td>
      <td>Hata sözleşmesi tanımlıdır</td>
    </tr>
    <tr>
      <td>Uygulamaya bağımlıdır</td>
      <td>Temsil bağımsızdır</td>
    </tr>
    <tr>
      <td>Her işi tek metotta toplar</td>
      <td>Küçük ve anlamlı işlemler kullanır</td>
    </tr>
  </tbody>
</table>

<h2 id="i̇yi-bir-adt-için-kısa-kontrol-listesi">İyi bir ADT için kısa kontrol listesi</h2>

<p>Arayüzü mümkün olduğunca küçük tutun, metotlara niyet belirten adlar verin ve iç nesnelerin değiştirilebilir kopyalarını dışarı sızdırmayın. Geçersiz durumları mümkünse oluşturulamaz hâle getirin; mümkün değilse girişleri doğrulayın. Son olarak testleri iç diziye göre değil, gözlemlenebilir davranışa göre yazın.</p>

<p>Özetle ADT tasarlamak yalnızca veriyi saklamak değildir. Asıl amaç, yanlış kullanımı zorlaştıran ve uygulama ayrıntılarının özgürce değişmesine izin veren bir sözleşme kurmaktır. İyi bir ADT, kullanıcıya düğmeleri gösterir; kablo karmaşasını ise kapağın altında bırakır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="soyut veri tipleri" /><category term="adt" /><category term="veri yapıları" /><category term="kapsülleme" /><category term="arayüz tasarımı" /><category term="typescript" /><summary type="html"><![CDATA[Bir kahve makinesini kullanmak için içindeki pompanın basıncını veya ısıtıcının devresini bilmemiz gerekmez; düğmeye basar, kahvemizi alırız. Soyut Veri Tipleri de benzer biçimde çalışır: Kullanıcıya ne yapılabileceğini gösterirken bunun nasıl yapıldığını gizler. Böylece veri yapıları daha güvenli, değiştirilebilir ve anlaşılır hâle gelir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/soyut-veri-tipleri-24.png" /><media:content medium="image" url="https://program.sonsuz.us/img/soyut-veri-tipleri-24.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>