递归届的Hello World
Fibonacci数列,又称黄金分割数列,由数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。由于其在数学上以递推的方法定义,因此很多人在讲解递归算法的时候,喜欢用Fibonacci作为例子。今天,我们来看看Fibonnacci的三种实现方式。
最简单的递归实现
第一种实现,也是最直观最简单的递归实现,如下:
unsigned int Fibonacci_1(unsigned int n) {
if (n == 0) {
return 0;
}
if (n == 1) || (n == 2) {
return 1;
}
return Fibonacci_1(n - 1) + Fibonacci(n - 2);
}
优化后的递归
前一种实现方式的优点是直观易懂,那么他有没有什么缺点呢?答案是有的,那就是效率,如下:
// F(n)
// / \
// F(n-1) F(n-2)
// / \ / \
// F(n-2) F(n-3) F(n-3) F(n-4)
可以看到,这里有很多重复计算,每一个F(n) 都可能被重复计算,n约小,重复计算的次数越多,那么有没有优化的地方呢?答案还是有的。如下:
#define N 100
unsigned int Fibonacci_2(unsigned int n) {
static unsigned int v[N] = {0};
if (n == 0) {
return 0;
}
if (v[n] != 0) {
return v[n];
}
if (n == 1) || (n == 2) {
v[n] = 1;
} else {
v[n] = v[n-1] + v[n-2];
}
return v[n];
}
非递归实现
除了递归实现,也可以非递归的方式实现,如下:
unsigned int Fibonacci_3(unsigned int n) {
if (n == 0) {
return 0;
}
if (n == 1) || (n == 2) {
return 1;
}
unsigned v1 = 1, v2 = 1, vn = 0;
for unsigned int i = 3; i <= n; i++ {
vn = v1 + v2;
v1 = v2;
v2 = vn;
}
return vn;
}
未结的结语
理论上讲,第一种效率最低,待改天补充测试数据。