<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>thexpot.net &#187; Algoritmalar</title>
	<atom:link href="http://www.thexpot.net/tag/algoritmalar/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thexpot.net</link>
	<description>...olur arada öyle...</description>
	<lastBuildDate>Mon, 18 Jan 2010 13:23:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Dijkstra&#8217;nın En Kısa Yol Algoritması</title>
		<link>http://www.thexpot.net/2008/05/dijkstranin-en-kisa-yol-algoritmasi/</link>
		<comments>http://www.thexpot.net/2008/05/dijkstranin-en-kisa-yol-algoritmasi/#comments</comments>
		<pubDate>Sun, 18 May 2008 17:06:27 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[Algoritmalar]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dijkstra'nın en kısa yol algoritması (DJK) ya da Dijkstra'nın deyişiyle "benim en kısa yol algoritmam"&#160; graf üzerinde bir noktadan diğer tüm noktalara en kısa yolu çıkarır ve bunu n noktalı bir grafta en kötü olarak O(n*n) zorlukta tamamlar. Daha önceden bahsettiğim <a href="http://www.thexpot.net/?q=node/107" target="_blank">Floyd-Warshall algoritması</a> ise tüm noktalar arasındaki en kısa mesafeyi O(n*n*n) zorlukta çıkarıyordu. Dikkat ettiyseniz birisi yolu diğeri mesafeyi çıkarıyor.]]></description>
			<content:encoded><![CDATA[<p>Dijkstra&#8217;nın en kısa yol algoritması (DJK) ya da Dijkstra&#8217;nın deyişiyle &#8220;benim en kısa yol algoritmam&#8221;  graf üzerinde bir noktadan diğer tüm noktalara en kısa yolu çıkarır ve bunu n noktalı bir grafta en kötü olarak <code>O(n*n)</code> zorlukta tamamlar. Daha önceden bahsettiğim <a href="http://www.thexpot.net/2008/01/floyd-warshall/" target="_blank">Floyd-Warshall algoritması</a> ise tüm noktalar arasındaki en kısa mesafeyi O(n<em>n</em>n) zorlukta çıkarıyordu. Dikkat ettiyseniz birisi yolu diğeri mesafeyi çıkarıyor.
Algoritmanın aşamalarını ayrı ayrı değerlendirdiğimizde anlamamız daha kolay olacaktır. Örnek olarak 10&#215;10&#8242;luk bir tahtanın üzerinde olduğumuzu düşünün. İlerlemeye (0,0) noktasından başlayıp, (9,9) noktasına ulaşmaya çalışacağız. Tahta üzerindeki her karede bir sayı olsun ve biz o kare üzerine geldiğimizde orada yazılı olan sayı kadar saniye beklemek zorunda kalalım. Bu durumda hedefimiz olan (9,9) noktasına en kısa zamanda nasıl ulaşırız?
<span id="more-112"></span>
Başlangıç noktasının diğer tüm noktalara olan mesafesini tutmak için bir tane Distance dizisine ve gittiğimiz yolu hatırlamamız için ise Previous dizisine ihtiyacımız olacak. Dizinin her elemanı tahta üzerindeki bir koordinata karşılık gelecektir. Örneğin (3,8) noktasının indeksini 3*Genişlik + 8 = 38 olarak hesaplayabiliriz. Başlangıç noktasının üzerinde olduğumuz için buraya olan mesafemiz 0, diğer tüm noktalara olan mesafemiz ise sonsuz olsun:</p>

<pre class='prettyprint'><code>Distances = new int[W*H];
Previous = new int[W*H];
for (int i = 0; i &lt; W*H; i++)
{
  Distances[i] = INF;
  Previous[i] = -1;
}
Distances[0] = 0;
</code></pre>

<p>Algoritmadaki her adımda kaynak bir nokta seçip, bu noktadan komşu noktalara gitmenin bize maliyetini hesaplayacağız ve bu nokta için bir daha hesap yapmayacağız. Bu yüzden hangi noktalar üzerinde çalıştığımızı da bir şekilde tutmamız gerekiyor. Bunun için bir liste kullanabilirsiniz. Gidilen noktaları listeden çıkarıp geriye kalanlar içinde hedefe en yakın olanı seçerek devam edebilirsiniz. Liste boşalana kadar bu işleme devam edip tüm noktalar için hesaplamalarımızı yapmış oluruz:</p>

<pre class='prettyprint'><code>var list = new List&lt;int&gt;();
for (int i = 0; i &lt; W * H; i++) list.Add(i);
while(list.Count &gt; 0)
{
  //hesaplamalar
}
</code></pre>

<p>Çapraz hareketler yapamayacağımız için her kare üzerinde gidilebilecek 4 yön var: sağa, sol, yukarı ve aşağı.</p>

<pre class='prettyprint'><code>private static readonly int[] dx = { 1, 0, -1, 0 };
private static readonly int[] dy = { 0, 1, 0, -1 };
</code></pre>

<p>Tüm bu yönlere hareket etmenin bizim için maliyeti nedir hesaplayalım ve Distance dizisinde bu noktaya karşılık gelen indekse bu değeri yazalım.</p>

<pre class='prettyprint'><code>while (list.Count &gt; 0)
{
  // hedefe en yakın noktanın indeksini al
  int bi = GetClosestIndex(list);
  int cx = bi % W, cy = bi / W; 

  for (int i = 0; i &lt; dx.Length; i++ )
  {
    int nx = cx + dx[i];
    int ny = cy + dy[i];
    // dışarıda kalıyorsa çık
    if (0 &gt; nx || nx &gt;= W || 0 &gt; ny || ny &gt;= H) continue;
    int ci = ny * W + nx;
    // bi'den ci'ye gidersek maliyeti nedir
    int cost = CostOfGoing(bi,ci);
    int alt = Distances[bi] + cost;
    //daha kazançlıysa burdan gidelim
    if (Distances[ci] &gt; alt)
    {
      Distances[ci] = alt;
      Previous[ci] = bi;
    }
  }
}
</code></pre>

<p>Bu işlem tüm noktalar için yapıldığında hedef noktanın kaynak noktaya olan mesafesi Distance[Hedef] olacaktır. Gidilecek yol ise şöyle çıkarılabilir:</p>

<pre class='prettyprint'><code>int target = 99;
List path = new List&lt;int&gt;();
while(Previous[target]!=-1)
{
    path.Add(target);
    target = Previous[target];
}
path.Reverse();
</code></pre>

<p>Dijkstra Algoritmasının en güçlü taraflarından birisi, çalışma süresinin kısa olmasıdır. Örnekte, kaynaktan başlayarak diğer tüm noktalara olan mesafeyi hesaplıyoruz sonra hedefimize giden yolu çıkarıyoruz. Bunu tüm noktalar için yapmak zorunda değiliz; eğer isterseniz algoritma içinde bi = target olduğu zaman algoritmayı sonlandırarak çalışma süresini de kısaltmış olabiliriz.
İkinci olarak ise; bir noktanın diğer noktaya olan mesafesini bir maliyet fonksiyonu ile hesaplıyorruz. Sadece bu fonksiyonu değiştirerek farklı sonuçlar elde edebiliriz. Örneğin; tahtanın üzerindeki her kareyi bir tepe olarak düşünelim ve üzerindeki sayı ise o tepenin yüksekliği olsun. Bir tepeden diğerine geçerken; tırmanmamız yükseklik farkı kadar, aşağı inmemiz ise yükseklik farkının yarısı kadar zaman alsın. Bu durumda maliyet fonksiyonumuzu aşağıdaki gibi değiştirmek bize istediğimiz sonucu verecektir:</p>

<pre class='prettyprint'><code>private int GetCostOfGoing(int bi, int ci)
{
    int diff = Height[bi] - Height[ci];
    if (diff &lt; 0) return -diff / 2;
    return diff;
}
</code></pre>

<p>Tüm bu işlemi görsel olarak takip etmeniz için bir WPF projesi hazırladım. <a href="http://www.thexpot.net/files/dijkstra.zip" target="_blank">Buradan</a> indirip inceleyebilirsiniz.</p>

<p>DipNot: Bu yazıyı, yazarken kaybettiğim o tuşuma armağan ediyorum.
<img src="http://www.thexpot.net/img/o.png" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2008/05/dijkstranin-en-kisa-yol-algoritmasi/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Floyd-Warshall Algoritması</title>
		<link>http://www.thexpot.net/2008/01/floyd-warshall-algoritmasi/</link>
		<comments>http://www.thexpot.net/2008/01/floyd-warshall-algoritmasi/#comments</comments>
		<pubDate>Mon, 14 Jan 2008 19:04:35 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[Algoritmalar]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Floyd-Warshall, graf olarak ifade edilebilecek herhangi bir veri yapısında herhangi iki nokta arasındaki en kısa yolu bulmak için kullanılabilecek kodlaması oldukça basit bir algoritmadır. 

İnternette bu algoritmayı anlatan birçok kaynak bulabilirsiniz. Benim burada anlatacaklarım ise minimum teori ile maksimum pratik sunmak olacak. Pseudo kod yerine örnekler ve kod parçaları üzerinden açıklamaya çalışacağım. Floyd-Warshall algoritmasının özü çok basit bir formülden oluşuyor. A,B,C diye 3 tane noktamız olduğunu varsayalım. Bu durumda A ile C arasındaki en kısa mesafe min(mesafe(A,C), mesafe(A,B) + mesafe(B,C)) kadar olacaktır. ]]></description>
			<content:encoded><![CDATA[<p>Floyd-Warshall Algoritması, graf olarak ifade edilebilecek herhangi bir veri yapısında herhangi iki nokta arasındaki en kısa yolu bulmak için kullanılabilecek kodlaması oldukça basit bir algoritmadır.
İnternette bu algoritmayı anlatan birçok kaynak bulabilirsiniz. Benim burada anlatacaklarım ise minimum teori ile maksimum pratik sunmak olacak. Pseudo kod yerine örnekler ve kod parçaları üzerinden açıklamaya çalışacağım. Floyd-Warshall algoritmasının özü çok basit bir formülden oluşuyor. A,B,C diye 3 tane noktamız olduğunu varsayalım. Bu durumda A ile C arasındaki en kısa mesafe <code>min(mesafe(A,C), mesafe(A,B) + mesafe(B,C))</code> kadar olacaktır.
<span id="more-107"></span>
Floyd-Warshall&#8217;ı uygulayabilmek için bir tabloya ihtiyacımız var. Bu tablonun boyutu nokta sayısına bağlı olarak belirlenecek. N tane noktamız var ise tablonun ebatları <code>N*N</code> olacaktır.
<img src="http://www.thexpot.net/img/107graf1.png" border="0" alt="" align="right" />Sağdaki örnek resme baktığımızda 5 nokta ve 5 kenardan oluşan bir graf görüyoruz. Bu grafdaki her bir kenar bitişikliği temsil ediyor. Bu durumda oluşturmamız gereken tablonun boyutu 5*5 olmalıdır.</p>

<pre class='prettyprint'><code>int[,] table = new int[5,5];
</code></pre>

<p>Algoritmanın temelinde min fonksiyonu kullanıldığı için bu tablonun girdilerinin ilk değerleri maksimum olarak atıyoruz. Her bir noktanın kendine olan mesafesini 0, diğer noktalara olan mesafesini ise sonsuz kabul ederek başlayacağız.</p>

<pre class='prettyprint'><code>int INFINITY = 9999999;
int N = 5;
for (int i = 0; i &lt; N; i++)
  for(int j = 0; j &lt; N; j++)
    table[i,j] = i == j ? 0 : INFINITY;
</code></pre>

<p>Bu işlemden sonra tablonun ilk değerleri aşağıdaki gibi olacaktır.
<table border="0" cellspacing="0" cellpadding="2" align="center">
<tbody>
<tr>
<td>table</td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
<td><strong>5</strong></td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>0</td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>INF</td>
<td>0</td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>INF</td>
<td>INF</td>
<td>0</td>
<td>INF</td>
<td>INF</td>
</tr>
<tr>
<td><strong>4</strong></td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
<td>0</td>
<td>INF</td>
</tr>
<tr>
<td><strong>5</strong></td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
<td>0</td>
</tr>
</tbody></table>
İkinci olarak noktalar arasındaki bağlantıları tutmak ve sorgulamak için <a href="http://en.wikipedia.org/wiki/Adjacency_matrix" target="_blank">bitişiklik matrisi</a> oluşturmalıyız. Eğer bir noktadan diğerine bir kenar var ise tabloda o girdiye 1 değerini veriyoruz. Örneğin nokta 2&#8242;den nokta 3&#8242;e ve nokta 4&#8242;e birer kenar bulunuyor. Bundan dolayı tablomuzun <code>[2,3] = [2,4] = 1 = [3,2] = [4,2]</code>. Grafımız yönlü olmadığı için elde ettiğimiz bitişiklik matrisinin diyagonale göre simetrik olması gerekiyor. Çünkü 1&#8242;den 4&#8242; e kenar varsa bu aynı zamanda 4&#8242;den 1&#8242;e de kenar var anlamına gelmektedir. Eğer örneğimiz yönlü bir graf olsaydı bunu söyleyemezdik. Bu işlemden sonra tablomuzun son hali aşağıdaki gibi olacak:
<table border="0" cellspacing="0" cellpadding="2" align="center">
<tbody>
<tr>
<td>table</td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
<td><strong>5</strong></td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>0</td>
<td>INF</td>
<td>INF</td>
<td>1</td>
<td>INF</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>INF</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>INF</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>INF</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>INF</td>
</tr>
<tr>
<td><strong>4</strong></td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td><strong>5</strong></td>
<td>INF</td>
<td>INF</td>
<td>INF</td>
<td>1</td>
<td>0</td>
</tr>
</tbody></table>
Simdi Floyd-Warshall formülünü uygulayabiliriz:
<pre class="prettyprint">for( int k = 0; k &lt; N; k++)
  for( int i = 0; i &lt; N; i++)
    for( int j = 0; j &lt; N; j++)
      table[i,j] = Math.Min(table[i,j], table[i,k] + table[k,j]);</pre>
Hepsi bu kadar. Bu işlemden sonra tablomuzun son hali şu şekilde olacak.
<table border="0" cellspacing="0" cellpadding="2" align="center">
<tbody>
<tr>
<td>table</td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
<td><strong>5</strong></td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>0</td>
<td>2</td>
<td>2</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>2</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>2</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td><strong>4</strong></td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td><strong>5</strong></td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>1</td>
<td>0</td>
</tr>
</tbody></table>
Artık tabloyu kullanarak her iki nokta arasındaki (a,b) en kısa mesafeyi sorgulayabiliriz. table[a,b] = table[b,a]
Şimdi biraz koda yüklenelim ve daha değişik bir örnek üzerinde çalışalım. Farz edelim ki bize bir harita verilmiş ve A noktasından B noktasına en kısa mesafeyi bulmamız istenmiş olsun.</p>

<pre class='prettyprint'><code>.......AXXXXXXX
..........X...X
.....XXXXXXXXXX
.....X........X
.XXXXXXXXXXXXXX
.X.....X..X....
.X.....X..X...X
.XXXXXXXXXXBXXX
</code></pre>

<p>X olan noktalar gidilebilecek yolu ifade etsin. Harita üzerindeki her bir karakteri yukarıdaki graftaki bir nokta olarak kabul edebiliriz. Bu durumda elimizde genişlik * yükseklik kadar nokta olacaktır. Her bir noktanın tablodaki yerini de (satır * genişlik) + sütun olarak belirleyebiliriz. Bitişiklik matrisini oluştururken her bir noktanın sağındaki, solundaki, üstündeki ve altındaki karakterlerin X,A,B karakterlerinden biri olup olmadığını kontrol etmek yeterli olacaktır. Eğer bu karakterlerden birisi ise kenar var diyeceğiz ve tabloya 1 değerini atayacağız. Örnek kod aşağıdaki gibi:</p>

<pre class='prettyprint'><code>private readonly string[] map = new string[]
     {
        ".......AXXXXXXX",
        "..........X...X",
        ".....XXXXXXXXXX",
        ".....X........X",
        ".XXXXXXXXXXXXXX",
        ".X.....X...X..X",
        ".X.....X...X..X",
        ".XXXXXXXXXXBXXX",
     };

int findShortestPath()
{
  int width = map[0].Length;
  int height = map.Length;
  int N = width*height;
  int[,] table = new int[N,N];
  int INF = 9999999;

  //tablonun ilk değerlerini atıyoruz
  for (int i = 0; i &lt; N; i++)
    for (int j = 0; j &lt; N; j++)
      table[i, j] = i == j ? 0 : INF;

  // bitişiklik matrisini oluşturuyoruz
  for (int i = 0; i &lt; N; i++)
  {
    int row = i/width;
    int col = i%width;
    if (map[row][col] == '.') continue;
    // yapılabilecek tüm hareketler için olasıkları üretiyoruz
    // ve kontrol ediyoruz
    for (int dx = -1; dx &lt;= 1; dx++)
      for (int dy = -1; dy &lt;= 1; dy++)
      {
        // (1,1) (1,-1) gibi hareketler yapamıyoruz
        if (Math.Abs(dy) + Math.Abs(dx) == 2) continue;
        if (col + dx &lt; width &amp;&amp; col + dx &gt;= 0 &amp;&amp;
            row + dy &lt; height &amp;&amp; row + dy &gt;= 0)
        {
          char c = map[row + dy][col + dx];
          if (c == 'X' || c == 'A' || c == 'B')
          {
            int newindex = (row + dy)*width + col + dx;
            table[i, newindex] = table[newindex, i] = 1;
          }
        }
      }
    }

  for (int k = 0; k &lt; N; k++)
    for (int i = 0; i &lt; N; i++)
      for (int j = 0; j &lt; N; j++)
        table[i, j] = Math.Min(table[i, j], table[i, k] + table[k, j]);

  string joined = String.Join(String.Empty, map);
  int startIndex = joined.IndexOf('A');
  int endIndex = joined.IndexOf('B');
  return table[startIndex, endIndex];
</code></pre>

<p>}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2008/01/floyd-warshall-algoritmasi/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Yayılma Öncelikli Arama (Breadth-First Search)</title>
		<link>http://www.thexpot.net/2007/10/yayilma-oncelikli-arama/</link>
		<comments>http://www.thexpot.net/2007/10/yayilma-oncelikli-arama/#comments</comments>
		<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[Algoritmalar]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Recursion doğru kullanıldığı zaman çok işimize yarayabilir. Özellikle ağaç tipi data yapılarının tüm nodelarını dolaşmak istediğimizde recursiondan faydalanabiliriz. Fakat bu ağaç yapısının ne kadar derinliğe sahip olduğunu kestiremediğimiz durumlarda bu yönteme çok da bel bağlamamak lazım zira stack (yığın) taşabilir ve overflow hatasıyla karşılaşabiliriz.

Alternatif bir yöntem ise kendi yığınımızı kullanarak bu işi yapmaktır. 
Genel adı ile Breadth First Search (Yayılma Öncelikli Arama):
<ul>
<li>Bir stack yaratılır ve root node'u bu yığına eklenir. (Queue ile de yapılabilir sadece işleme sıranız değişir)
<li>Herhangi bir node'un alt node'ları varsa bunlar da yığına eklenir
<li>Bulunduğumuz node işlenir ve yığından bir sonraki node çekilir. 
<li>Yığın boşalana kadar bu işlem tekrarlanır.
</ul>

Tüm dizin yapısını dolaşan örnek kod:]]></description>
			<content:encoded><![CDATA[<p>Recursion doğru kullanıldığı zaman çok işimize yarayabilir. Özellikle ağaç tipi data yapılarının tüm nodelarını dolaşmak istediğimizde recursiondan faydalanabiliriz. Fakat bu ağaç yapısının ne kadar derinliğe sahip olduğunu kestiremediğimiz durumlarda bu yönteme çok da bel bağlamamak lazım zira stack (yığın) taşabilir ve overflow hatasıyla karşılaşabiliriz.</p>

<p>Alternatif bir yöntem ise kendi yığınımızı kullanarak bu işi yapmaktır.
Genel adı ile Breadth First Search (Yayılma Öncelikli Arama):
<ul>
    <li>Bir stack yaratılır ve root node&#8217;u bu yığına eklenir. (Queue ile de yapılabilir sadece işleme sıranız değişir)</li>
    <li>Herhangi bir node&#8217;un alt node&#8217;ları varsa bunlar da yığına eklenir</li>
    <li>Bulunduğumuz node işlenir ve yığından bir sonraki node çekilir.</li>
    <li>Yığın boşalana kadar bu işlem tekrarlanır.</li>
</ul>
Tüm dizin yapısını dolaşan örnek kod:
<span id="more-98"></span>
<pre class="prettyprint">
Stack stack = new Stack();
stack.Push(new DirectoryInfo(@"c:\"));
while(stack.Count > 0)
{
  DirectoryInfo dir = stack.Pop();
  Console.WriteLine(dir.FullName);
  foreach (DirectoryInfo info in dir.GetDirectories())
    stack.Push(info);
}
</pre>
Queue kullanarak ise:
<pre class="prettyprint">
Queue queue = new Queue();
queue.Enqueue(new DirectoryInfo(@"c:\"));
while(queue.Count > 0)
{
  DirectoryInfo dir = queue.Dequeue();
  Console.WriteLine(dir.FullName);
  foreach (DirectoryInfo info in dir.GetDirectories())
    queue.Enqueue(info);
}
</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2007/10/yayilma-oncelikli-arama/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Expression Evaluation</title>
		<link>http://www.thexpot.net/2005/11/expression-evaluation/</link>
		<comments>http://www.thexpot.net/2005/11/expression-evaluation/#comments</comments>
		<pubDate>Thu, 17 Nov 2005 18:28:43 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[Algoritmalar]]></category>
		<category><![CDATA[Delphi]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Merhaba,

Recursion yöntemini kullanarak neler yapılabileceğini göstermek amacıyla
<blockcode highlight="off">
     12
  -------- + 6
   13 + 1

<hr />

<pre class='prettyprint'><code>28
</code></pre>

</blockcode>
gibi ifadeleri (Expression) hesaplayan örnek bir program yazalım dedim.

Program bölme ve toplama işlemlerini tanıyabilecek. Bölme için gerekli çizgiler ‘-‘ karakteri kullanılarak çizilecek.

İfadeler ya bölme ya toplama işlemi olacak o yüzden şöyle bir class hiyerarşisi oluşturuyoruz.

İlk olarak bütün ifadelerin hesaplama yapan bir metodu olmalı ve bu metod Real bir değer döndürmeli. O yüzden TExpression diye abstract bir class tanımlıyoruz ve içine Evaluate metodunu yazıyoruz.]]></description>
			<content:encoded><![CDATA[<p>Merhaba,</p>

<p>Recursion yöntemini kullanarak neler yapılabileceğini göstermek amacıyla</p>

<pre class='prettyprint'><code>   12
-------- + 6
 13 + 1
 ------
   28
</code></pre>

<p>gibi ifadeleri (Expression) hesaplayan örnek bir program yazalım dedim.</p>

<p>Program bölme ve toplama işlemlerini tanıyabilecek. Bölme için gerekli çizgiler ‘-‘ karakteri kullanılarak çizilecek.</p>

<p>İfadeler ya bölme ya toplama işlemi olacak o yüzden şöyle bir class hiyerarşisi oluşturuyoruz.</p>

<p>İlk olarak bütün ifadelerin hesaplama yapan bir metodu olmalı ve bu metod Real bir değer döndürmeli. O yüzden TExpression diye abstract bir class tanımlıyoruz ve içine Evaluate metodunu yazıyoruz.
<span id="more-4"></span></p>

<pre class='prettyprint'><code>TExpression =  class
public
  function Evaluate:Real;virtual;abstract;
end;
</code></pre>

<p>Tek başına yazılmış bir sayı da bir çeşit ifade olduğu için TExpression classından TSingleExpression adında bir class türetiyoruz</p>

<pre class='prettyprint'><code>TSingleExpression = class(TExpression)
private
  FValue : Real;
public
  function Evaluate: Real;override;
  constructor Create(AValue : Real);
end;
</code></pre>

<p>Bu classın Evaluate metodu çalışıtırıldığında Fvalue alanındaki değeri döndürecek.</p>

<p>Toplama işlemi için TAdditionExpression adıyla bir class daha tanımlıyoruz:</p>

<pre class='prettyprint'><code>TAdditionExpression = class(TExpression)
protected
  FLeft : TExpression;
  FRight: TExpression;
public
  function Evaluate: Real;override;
  constructor Create(Left,Right:TExpression);
  destructor Destroy;override;
end;
</code></pre>

<p>Bu classın evaluate metoduda Fleft ve Fright alanlarındaki Expression classlarının evaluate metodlarını çalıştırıp çıkan sonucu toplayarak döndürecek</p>

<p>Bölme işlemi de toplama işleminden çok farklı olmadığı için</p>

<pre class='prettyprint'><code>TDivisionExpression = class(TAdditionExpression)
public
  function Evaluate: Real;override;
end;
</code></pre>

<p>Program şöyle bir algoritma izleyecek:</p>

<pre class='prettyprint'><code>function Parse(Lines: TstringList):Texpression;
basla
  // bölme işlemi için
  eger &lt;&gt; basla
     &lt;&lt;İfadeyi o satırdan Sag ve Sol olamk üzere ikiye ayır&gt;&gt;
     Expr1 = parse(Sag);
     Expr2 = parse(Sol);
     Result := TDivisionExpression.Create(Expr1,Expr2);
     Exit;
  bitir;
  // toplama işlemi için
  eger &lt;&gt; basla
     &lt;&lt;İfadeyi o sütundan Ust ve Alt olam üzere ikiye ayır&gt;&gt;
     Expr1 = parse(Ust);
     Expr2 = parse(Alt);
     Result := TAdditionExpression.Create(Expr1,Expr2);
     Exit;
  bitir;
  // sayılar için
  eger &lt;&gt; basla
     Result := TSingleExpression.Create(Deger)
  bitir;
  // hiçbir koşula düşmediyse
  Hata;
bitir;
</code></pre>

<p>Hesaplama işlemi aşağıdaki kodla yapılabilecek</p>

<pre class='prettyprint'><code>var
  Exp : TExpression;
begin
Exp:=Parse(memo1.lines);
ShowMessage(FloatToStr(Exp.Evaluate));
End;
</code></pre>

<p>Metod çalıştırıldığında recursive olarak İfade Ağacı (Expression Tree) oluşturulacak.</p>

<p>Kaynak Kod: <a href="http://www.thexpot.net/files/memoevaluate.rar">memoevaluate.rar</a>
Çalıştırılabilir Dosya : <a href="http://www.thexpot.net/files/memoevaluate.exe.rar">memoevaluate.exe.rar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2005/11/expression-evaluation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backtracking</title>
		<link>http://www.thexpot.net/2005/11/backtracking/</link>
		<comments>http://www.thexpot.net/2005/11/backtracking/#comments</comments>
		<pubDate>Thu, 17 Nov 2005 17:25:09 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[Algoritmalar]]></category>
		<category><![CDATA[Delphi]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Merhaba arkadaşlar,
İlk algoritma olarak kodlaması kolay ama kolay olduğu kadarda masraflı çok olan “Aynı yere geri dönme” (Backtrack) algoritmasını seçtim. Makelenin geri kalanında backtrack olarak söz edeceğim.

Backtrack algoritması özyineleme (recursion) desteklenen her dilde kodlanabilir ve basit bir algoritma olmasına rağmen de bir çok ufak iş için kullanılabilir. Bu algoritmanın dezavantajı maximum adım sayısı bilinmeyen durumlarda stackoverflow hatasına neden olabilmesidir.

Algoritmanın pseudo-code’u aşağıdaki gibi :
<code>
  procedure backtrack(i:integer;deger: integer);
  basla
    Eger sonuclardan-biriyse
      &#60;&#60; sonucla ilgili islemleri yap >>
    degilse
       her adaydeger icin backtrack(i+1,adaydeger);
    bitir;]]></description>
			<content:encoded><![CDATA[<p>Merhaba arkadaşlar,
İlk algoritma olarak kodlaması kolay ama kolay olduğu kadarda masraflı çok olan “Aynı yere geri dönme” (Backtrack) algoritmasını seçtim. Makelenin geri kalanında backtrack olarak söz edeceğim.</p>

<p>Backtrack algoritması özyineleme (recursion) desteklenen her dilde kodlanabilir ve basit bir algoritma olmasına rağmen de bir çok ufak iş için kullanılabilir. Bu algoritmanın dezavantajı maximum adım sayısı bilinmeyen durumlarda stackoverflow hatasına neden olabilmesidir.</p>

<p>Algoritmanın pseudo-code’u aşağıdaki gibi :</p>

<pre class='prettyprint'><code>procedure backtrack(i:integer;deger: integer);
basla
  Eger sonuclardan-biriyse
    &lt;&lt; sonucla ilgili islemleri yap &gt;&gt;
  degilse
    her adaydeger icin backtrack(i+1,adaydeger);
  bitir;
bitir;
</code></pre>

<p>Tabi ilk bakışta bu pseudo-code’dan her şeyi anlamak kolay değil, o yüzden hemen bir örnek verelim. Bu algoritmayı kullanarak bir kümenin bütün alt kümelerini oluştururalım. Kümemiz 1’den 5’e kadar olan sayılardan oluşsun. Algoritmada bahsi geçen her adım için adaylar true ve false değerlerini alacak. Yani herhangi bir indexdeki eleman o altkümenin içindeyse true değilse false olarak işaretlenecek. Eger adım sayısı kümenin eleman sayısına eşit olduysa tüm kombinasyonlar üretildi demektir, sonucu ekrana yazıyoruz. Eger adım sayısı kümenin eleman sayısından küçükse daha üretilmesi gerek kombinasyonlar var demektir, bizde bir sonraki adım için tüm olası değerleri veriyoruz.</p>

<pre class='prettyprint'><code>arr : array[1..5] of boolean;

procedure Recurse(i : integer; val:boolean);
var 
  j : integer;
begin
  arr[i]:= val;
  if (i=Length(arr)) then begin
    Write('{ ');
    for j := 0 to Length(Arr) do  if(arr[j]) then Write(j,' ');
    WriteLN(' }');
  end else begin
    recurse(i+1,true);
    recurse(i+1,false);
  end;
end;
begin
  recurse(1,true);
  recurse(1,false);
  readln;
end.
</code></pre>

<p>n elemanlı bir kümenin 2^n tane altkümesi vardır, dolayısıyla örneği çalıştırdığımızda 32 tane sonuç göreceğiz.</p>

<p>İkinci örnek olarak da bir string içindeki karakterlerin bütün permütasyonlarını oluşturalım. Yine aynı mantığı kullanıcaz ama bu sefer biraz daha fazla çalışmamız lazım.</p>

<pre class='prettyprint'><code>var
  str : string = 'ABC';

 procedure backtrack(str:string;i:integer);
 var
  j: integer;
  ch : char;
 begin
   if i = length(str) then begin
     WriteLn(str);
   end else begin
     for j := i to length(str) do begin
        ch := str[i];
        str[i] := str[j];
        str[j] := ch;
        backtrack(str,i+1);
     end;
   end;
 end;

begin
  backtrack(str,1);
  Readln;
end.
</code></pre>

<p>Örnekteki i değeri str değişkeninin uzunluğuna denk olduğunda bunu ekrana yazıyoruz, eğer değilse i ve length(Str) arasındaki karakterleri str değişkeninin i. karakteri ile değiştirip prosedürü tekrar çağırıyoruz.
Üç karakterden oluşan stringin toplam 3! = 6 tane permütasyonu olması lazım, yalnız biz bunu yaparken bütün karakterlerin birbirinden farklı olduğunu farzediyoruz. ‘AAA’ şeklinde tanımlanmış bir değişkende birbirinin aynısı olmasına rağmen 6 tane satır göreceğiz.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2005/11/backtracking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
