1. 定義:
黄金分割数列としても知られるフィボナッチ数列は、数学者レオナルドフィボナッチによってウサギの飼育を例に紹介されたため、「ウサギ数列」とも呼ばれます。1、1、2、3のような数列です。、5、8、13、21、34、55、...このシーケンスは 3 番目の項目から始まり、各項目は前の 2 つの項目の合計に等しくなります。
2. n番目のフィボナッチ数を見つける方法:
(1) 再帰
#include<stdio.h>
int Fib(int n)
{
if (n <= 2)
{
return 1;
}
else
{
return Fib(n - 1) + Fib(n - 2);
}
}
int main()
{
int n = 0;
printf("input n: ");
scanf("%d", &n);
printf("%d\n",Fib(n));
return 0;
}
50 番目のフィボナッチ数が何であるかを確認するために 50 を入力してみましょう
カーソルが点滅し続け、プログラムが常に実行されていることがわかりますが、出力結果はありません。
繰り返し計算の回数が多く、決して少なくない作業量であることがわかりますが、あるフィボナッチ数が何回繰り返し計算されるかを計算することができます。
40 番目のフィボナッチ数を計算するときに、3 番目のフィボナッチ数が繰り返し計算される回数をカウントします (コードは次のとおりです)。
//递归法
#include<stdio.h>
int count = 0;//全局变量
int Fib(int n)
{
//统计的是 第3个斐波那契数被重复计算的次数
if (3 == n)
{
count++;
}
if (n <= 2)
{
return 1;
}
else
{
return Fib(n - 1) + Fib(n - 2);
}
}
int main()
{
int n = 0;
printf("input n: ");
scanf("%d", &n);
printf("%d\n",Fib(n));
printf("count= %d\n", count);
return 0;
}
コンピュータの計算量は非常に大きく、時間計算量と空間計算量が非常に高く、スタックオーバーフローやタイムアウトを引き起こしやすいことがわかります。したがって、ここで再帰を使用するのは明らかに賢明な選択ではありません。
(2) 反復
//迭代法
#include<stdio.h>
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n>2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
printf("input n: ");
scanf("%d", &n);
printf("%d\n",Fib(n));
return 0;
}
ループ反復法の効率は再帰の効率よりもはるかに高くなりますが、再帰コードの可読性はわずかに劣ります。
3. ヒント:
(1) 多くの問題は、非再帰形式よりも明確であるという理由だけで、再帰形式で説明されます。
(2) ただし、これらの問題の反復実装は、コードが若干読みにくくなりますが、多くの場合、再帰実装よりも効率的です。
(3) 問題が非常に複雑で、反復的に実装することが難しい場合、再帰的実装の単純さによって、それがもたらす実行時のオーバーヘッドを補うことができます。