Bir Fibbonacci dizisi, 1 ile başlayan önceki sonuca eklendiğinde bir sayının sonucunu toplayan dizidir.
so.. 1 + 1 = 2
2 + 3 = 5
3 + 5 = 8
5 + 8 = 13
8 + 13 = 21
Fibbonacci'nin ne olduğunu anladıktan sonra, kodu parçalamaya başlayabiliriz.
public int fibonacci(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
İlk if ifadesi, döngünün dağılabileceği bir temel durumu kontrol eder. Aşağıdaki ifadenin aynısını yapıyorsa, ancak bu şekilde yeniden yazılabilirse ...
public int fibonacci(int n) {
if(n < 2)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
Şimdi bir temel durum oluşturulduktan sonra çağrı yığınını anlamalıyız. "Fibonacci" ye ilk çağrınız, çağrıldıkları ters sırayla çözüldükleri için yığında (çağrıların sırası) çözülecek son çağrı olacaktır. Denilen son yöntem önce çözülür, sonra ondan önce çağrılacak son yöntem vb.
Böylece, tüm aramalar bu sonuçlarla bir şey "hesaplanmadan" önce yapılır. 8'lik bir girdi ile 21'lik bir çıktı bekliyoruz (yukarıdaki tabloya bakın).
fibonacci (n - 1) baz kasasına ulaşana kadar çağrılmaya devam eder, daha sonra fibonacci (n - 2) baz kasasına ulaşana kadar çağrılır. Yığın sonucu ters sırada toplamaya başladığında, sonuç şöyle olur ...
1 + 1 = 1 ---- last call of the stack (hits a base case).
2 + 1 = 3 ---- Next level of the stack (resolving backwards).
2 + 3 = 5 ---- Next level of the stack (continuing to resolve).
Yığındaki ilk çağrıya doğru toplam geri dönene kadar köpürmeye devam eder (geriye doğru çözümlenir) ve cevabınızı bu şekilde alırsınız.
Bunu söyledikten sonra, bu algoritma çok verimsizdir çünkü kodun ayrıldığı her dal için aynı sonucu hesaplar. Çok daha iyi bir yaklaşım, Memoization (önbellekleme) veya özyineleme (derin çağrı yığını) gerekmeyen "aşağıdan yukarıya" bir yaklaşımdır.
Bunun gibi ...
static int BottomUpFib(int current)
{
if (current < 2) return current;
int fib = 1;
int last = 1;
for (int i = 2; i < current; i++)
{
int temp = fib;
fib += last;
last = temp;
}
return fib;
}