Java A/Ö 3 Recursive ve Binary Search (Devamı)

narutomanga899

Katılımcı Üye
21 Nis 2013
384
0
City of Code
Önceki kaldığımız yerden Shuffle sorusunun cevabı;
Kod:
public static **** shuffle(double[] a)
{
     int N = a.length;

     for (int i = 0; i < N; i++)
     { 
          int r = i + StdRandom.uniform(N-i); // 1.olay

          double temp = a[i];  //Buradan itibaren 2. olay
          a[i] = a[r];
          a[r] = temp;
     }
}

public static int uniform(int N)
{ 
     return (int) (StdRandom.random() * N); 
}

-Evet, bu soruda uniform methodumuzda 0 ile N arasında rastgele bir int sayısı (double değil) belirliyoruz.

-Shuffle methoduna baktığımızda, for döngüsünde N’ye kadar gidiyoruz ve yeni bir r sayısı belirliyoruz. Bu r sayısı I + ratgele uniform metodu(N-i) olacak şekilde çağırıyoruz ve bununla r sayımız her I değiştiğinde başka ratgele sayı olarak belirleniyor. Sonrada a ile a[r] ninci sayıları birbirleriyle tekrar karıştırıyoruz.

-Böylece önce baştan sona her array elemanına rastgele sayılar belirlemiş olduk(1.olay)
-Belirlenen bu sayıları birbirleriyle tekrar karıştırdık(2.olay)

-------
Soru- Şimdi recursive bir örnek olan Binary Search’e bakalım

Bazı önemli algoritmalar searching(arama) ve sorting(sıralama) olarak ayrılmıştır, bunlar programları hızlı çalıştırmada etkindirler, bu methodlar bazen normal for döngüleri gibi linear olarak yazıldığında daha hızlı çalşırken, bazende recursive gibi kendini tekrar tekrar çağırma methoduyla daha hızlı çalışırlar. Bu method tipleri, ileride program yazılacağı zaman verimlilik açısından çok önemlidir çünkü kimse yavaş çalışan program istemez.

Binary Search dedğimiz örnekle bunlara girelim. Elimizde düzenli olarak sıralanmış küçükten büyüğe bir süre sayı olsun ama tüm sayılar olmasın, mesela a[] arrayinde;
1, 2, 5, 7, 8, 9, 14, 15, 18, 21, 25, 30 gibi ve key(bulmak istediğimiz sayı) 21 olsun.
bu sayıların içinden istediğimiz herhangi birini bulmak için en basit haliyle düşünürsek yapacağımız heralde for döngüsü içinde baştan sona kadar ilerleyip o sayıyı bulduğumuzda durmak olur, methodumuzun adı rank olsun;
Kod:
public static int rank(int key, int[] a)
{
     for (int i = 0; i < a.length; i++)
          if (a[i] == key) 
               return i;
     return -1;
}

Burada görüldüğü gibi kullanıcı key adında aramak istediği sayıyı ve a[] içinde aramak istediği arrayi girecek, bizden istenen o sayının dizide kaçıncı sırada olduğu,
For döngüsünde baştan sona tek tek gidecek ve eğer a ninci eleman key’e eşitse return i diyerek sırasını dönecek, eğer for bittiğinde bulamazsa return -1 diyerek içinde olmadığını belirleyecek.

Normalde bu yöntem ile kolayca bulduğumuzu düşünsekte ileride büyük projelerde, büyük methodlarda çok fazla CPU harcayacak ve program bu durum için yavaş çalışacak, burada recursive(kendi kendini çağıran) method kullanmak işi kat kat hızlandıracaktır,

Recursive methodlar for döngüsü gibi tekrar tekrar dönerler ancak mantık olarak biraz daha farklı, bu methodlar kendisini çağırabilir, mesela;
Kod:
public static int rank(int start, int end) {
     while(start != end)
	     return rank(start + 1, end);
     return -1;
}

Dediğimizde, start, end’e eşit olana kadar döngü devam edecek ve her seferinde rank methodunu tekrar çağırdığında start, birdahakine start + 1 den başlayacak, mesela start = 1, end = 5 olsun; start = 1 != 5 = end eşit olmadığı için while devam edecek ve rank methodunu tekrar çağırdığında start = start + 1 olacak ve artık 2 ye 5 oldu, birdahakine 3 e 5, sonra 4 e 5, en sondada 5 = 5 olacağı için return -1 den method bitecek, bu tür methodlara recursive diyoruz,

Şimdi Binary Searh’ü recursive yazalım;

Binary search’ün mantığı sayıyı bulmak için önce onu ortadaki sayıyla kıyaslarız, eğer sayı ortadakinde büyüksa sağ tarafa, küçükse sol tarafa bakarız, bir sonrakindede kalan sayının ortasına bakarız ve böyle en sona kadar gideriz, en sondada bulduğumuz sayıyı yazarız, kodumuz şöyle;

Kod:
public static int rank(int key, int[] a)
{ 
     return rank(key, a, 0, a.length - 1); 
}

public static int rank(int key, int[] a, int lo, int hi)
{ 
     if (lo > hi) 
          return -1;

     int mid = lo + (hi - lo) / 2;

     if (key < a[mid]) 
          return rank(key, a, lo, mid - 1);
     else if (key > a[mid])
          return rank(key, a, mid + 1, hi);
     else 
          return mid;
}

Burada kullanıcı sadece key sırası bulunacak sayıyı ve a[] array dizisini girmişti, ancak bizim işlem yapabilmek için daha fazla parametrelere(girdilere) ihtiyacımız var bunun için aynı isimde yeni bir method yazıyoruz[Not: Aynı isme sahip olup farklı parametrelere sahip olan method yazmaya overloading denir, method isimleri aynıdır ama farklı işlemler yapılır ,buna birbirlerini çağırmak dahil olduğu gibi birinde çarpma diğerinde bölme işlemi yapmak gibi şeylerde dahildir] ve ilk methodta ikincisini çağırıyoruz, ikinci methodtada key, a[] arrayinin yanında ilk pozisyon lo, ve son posizson hi alıyoruz.

-Sonra lo yani son eleman hi yani ilk elemanı geçtiğinde -1 dönecek yani o eleman baştan sona kadar gitti ama bulamadı, bu döngünün son basamağı.(genelde ilk yazılır)

-Yeni bir mid tanımlıyoruz ve ilk ve son eleman arasını buluyoruz

-key eğer a[mid] inci elemandan küçükse birdahakine rank’ı tekrar çağırdığımızda lo dan başlayacak ama son eleman mid – 1 de bitecek, yani döngüyü yarıya böldük.

-benzerini eğer büyükse diyoruz ve bu sefer mid+1 den başlıyoruz ve hi, son elemanına kadar gidecek, ve rank methodu tekrar yukarıdan aşağıya doğru çalışacak ama şartlarım az önce değiştirdiğimiz gibi

-en sonda küçük veya büyük olmadığı durumda tek bir eleman kalmış olacak ve o da mid olacak. Eğer kalmamış ve başlangıç lo > hi sondaki eleman olursa aradığımız key yok demektir ve -1 dönecek, varsa dediğimiz gibi mid’i dönecek.

Görüldüğü gibi Binary Search’ü Recursive ile çözmüş olduk ve bu bize normal for ile çözümden 4-5 kat daha hızlı çözüm sağlıyor ancak bu her durum için olmaz, bazen tam tersi olur onlara sonra bakacağız..
------------------------------
 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.