斐波那契數列的詳細定義可以查看斐波那契數列
看一些算法書,提到遞歸,經常會拿斐波那契數列來舉例,所以今天就寫點程序,簡單討論一下。
這裏包括了兩個方法,一個是遞歸計算,效率極其低下;另一種,就是直接利用循環計算,效率是就好很多,下面是代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace FibonacciNumber
{
class Program
{
// F(0) = F(1) = 1, F(n) = F(n-1) + F(n-2) (n>=2)
static void Main(string[] args)
{
Console.WriteLine("N\tValue\tCost(ms)");
for (ulong i = 1; i <= 50; ++i)
{
KeepTime(FibonacciNonRecursive, i);
}
Console.WriteLine("N\tValue\tCost(ms)");
for (ulong i = 1; i <= 50; ++i)
{
KeepTime(FibonacciRecursive, i);
}
}
static void KeepTime(Func<ulong, ulong> action, ulong index)
{
ulong value = 0;
Stopwatch time = new Stopwatch();
time.Start();
value = action(index);
time.Stop();
Console.WriteLine("{0}\t{1}\t{2}", index, value, time.ElapsedMilliseconds);
}
// Calculate Fibonacci Number recursively
static ulong FibonacciRecursive(ulong n)
{
if (n <= 1)
{
return 1;
}
else
{
return FibonacciRecursive(n - 1) + FibonacciRecursive(n - 2);
}
}
// Calculate Fibonacci Number non-recursively
static ulong FibonacciNonRecursive(ulong n)
{
if (n <= 1)
{
return 1;
}
else
{
ulong minusOne = 1;
ulong minusTwo = 1;
ulong value = 0;
for (ulong i = 2; i <= n; ++i)
{
value = minusOne + minusTwo;
minusTwo = minusOne;
minusOne = value;
}
return value;
}
}
}
}
FibonacciRecursive方法是遞歸算法
FibonacciNonRecursive方法是非遞歸算法
下面是兩個方法計算前50個數的時間:
N | Value | FibonacciNonRecursive Cost(ms) | FibonacciRecursive Cost(ms) |
1 | 1 | 0 | 0 |
2 | 2 | 0 | 0 |
3 | 3 | 0 | 0 |
4 | 5 | 0 | 0 |
5 | 8 | 0 | 0 |
6 | 13 | 0 | 0 |
7 | 21 | 0 | 0 |
8 | 34 | 0 | 0 |
9 | 55 | 0 | 0 |
10 | 89 | 0 | 0 |
11 | 144 | 0 | 0 |
12 | 233 | 0 | 0 |
13 | 377 | 0 | 0 |
14 | 610 | 0 | 0 |
15 | 987 | 0 | 0 |
16 | 1597 | 0 | 0 |
17 | 2584 | 0 | 0 |
18 | 4181 | 0 | 0 |
19 | 6765 | 0 | 0 |
20 | 10946 | 0 | 0 |
21 | 17711 | 0 | 0 |
22 | 28657 | 0 | 0 |
23 | 46368 | 0 | 0 |
24 | 75025 | 0 | 1 |
25 | 121393 | 0 | 2 |
26 | 196418 | 0 | 4 |
27 | 317811 | 0 | 6 |
28 | 514229 | 0 | 11 |
29 | 832040 | 0 | 18 |
30 | 1346269 | 0 | 29 |
31 | 2178309 | 0 | 47 |
32 | 3524578 | 0 | 77 |
33 | 5702887 | 0 | 122 |
34 | 9227465 | 0 | 199 |
35 | 14930352 | 0 | 324 |
36 | 24157817 | 0 | 526 |
37 | 39088169 | 0 | 857 |
38 | 63245986 | 0 | 1390 |
39 | 102334155 | 0 | 2267 |
40 | 165580141 | 0 | 3668 |
41 | 267914296 | 0 | 5902 |
42 | 433494437 | 0 | 9505 |
43 | 701408733 | 0 | 15374 |
44 | 1134903170 | 0 | 24746 |
45 | 1836311903 | 0 | 39804 |
46 | 2971215073 | 0 | 64230 |
47 | 4807526976 | 0 | 103802 |
48 | 7778742049 | 0 | 168007 |
49 | 12586269025 | 0 | 271728 |
50 | 20365011074 | 0 | 439400 |
從上圖可以看出,非遞歸方法非常快,時間複雜度是線性的,而遞歸方法,則要慢很多,基本感覺是指數級增長