サイトマップ / C言語講座>出入り口>総目次>目次:再帰>フィボナッチ数列を表示する関数(再帰改良版)
[フィボナッチ数列(再帰版)]←このソース→[フィボナッチ数列(動的計画法版)]
前回は、再帰的呼び出しでフィボナッチ数を求めました。そこでは、フィボナッチ数列の定義を素朴にソースプログラムにしました。それを下記に示します。
// nのフィボナッチ数を返す unsigned long Fibo(int n) { unsigned long f; // フィボナッチ数をしまう switch (n) { case 1: case 2: // n が1か2なら f = 1L; // f は1 break; default: // それ以外は f = Fibo(n - 1) + Fibo(n - 2); // 再帰呼び出し break; } return (f); // fの値をリターン }
しかし、このコードにはまだまだ改善の余地があります。それは、同じFibo( )が何度も呼ばれることです。このことを、オーバーヘッドが大きいといいます。
例えば、Fibo(6)が呼ばれると、Fibo(5)とFibo(4)が呼ばれます。呼ばれた Fibo(5)は、Fibo(4)とFibo(3)を呼びます。呼ばれたもう一方のFibo(4)は、Fibo(3)とFibo(2)を呼びます。結局、同じFibo( )が何度も呼ばれることになります。この様子を下記に示します。
繰り返し呼ばれるので、実行時間がかかります。そこで、何度も同じ計算をしないで済ますため、一度計算したFibo( )の値をresult[ ]という配列に保存し、再利用することで、効率化をはかったのが今回のソースプログラムです。
前回と名前の混同を避けるため、関数の名前をFibo2( )とします。
result[ ]は関数の外で宣言します。従って、静的領域に存在し、コンパイル時に0に初期化されます。また、プログラムの実行中常にメモリに存在し、関数から抜け出してもその値は保持されます(静的領域については、変数の記憶クラスと関数や変数のメモリ配置を参照のこと)。そのフィボナッチ数が既に計算済みであればその結果がresult[ ]に保存されています。
Fibo2(n)は呼ばれると、まず、下記の文を実行します。
if (f = result[n]) return (f);
nのフィボナッチ数が既に計算済みであれば、result[n]は0ではないので真となり、その値を返します。まだ、計算していなければ、 result[n]は0なので、偽となり、フィボナッチ数を計算します。
フィボナッチ数を計算する際、nは47が限度です。Cの配列の添字は0から始まります。result[46]は47番目になるので、配列のサイズは47になります。 */
#include <stdio.h> #include <stdlib.h> /* exit( )で必要 */ unsigned long Fibo2(int n); void main(void); #define MAX_VAL 48 unsigned long result[MAX_VAL]; /* ここに計算結果を保存 */ /* nのフィボナッチ数を返す */ unsigned long Fibo2(int n) { unsigned long f; if (f = result[n]) /* フィボナッチ数を計算済みなら */ return (f); /* fを返す */ /* まだなら */ switch (n) { /* フィボナッチ数を計算する */ case 1: case 2: /* nが1か2なら */ f = 1L; /* fは1L */ break; default: /* nが2以上なら */ f = Fibo2(n - 1) + Fibo2(n - 2); /* 再帰的呼び出し */ break; } result[n] = f; /* データを保存して */ return (f); /* fを返す */ } void main(void) { int n; /* nのフィボナッチ数を求める */ printf("1から47迄の整数を入力して下さい\t"); scanf("%d", &n); if(n > MAX_VAL - 1) { /* nが47より大きければ何もしないで終了 */ printf("数字が大き過ぎます\n"); exit(0); } /* フィボナッチ数を表示 */ printf("\nFibonacci 数は %lu\n", Fibo2(n)); } |
/* 前回の再帰版と比べて、実行速度はどうなりましたか。特に、nの値が大きい時に実行速度で大きな差が出たと思います。 */
[フィボナッチ数列(再帰版)]←このソース→[フィボナッチ数列(動的計画法版)]
/* (C) 2000- YFプロ. All Rights Reserved. */ 提供:C言語講座−それ自体コンパイルできる教材を使った講座です−