Subsections

3 再帰呼び出し

3.1 再帰呼び出しとは

関数の中で,自分自身の関数を呼び出すことを再帰呼び出し(recursive call)と言う.こ のアルゴリズムを使うと,ある種の問題に対して,手続きが非常に簡素に表現できること がある.

これは,実際にプログラムを示した方がよく分かるので,簡単な例を示す.数学で,演算子!で表される階乗という演算にしばしばお目にかかる.たとえば,5の階乗は

$\displaystyle 5!$ $\displaystyle =5\times 4\times 3\times 2\times 1$    
  $\displaystyle =120$ (1)

である.一般の整数$ n$ では,

$\displaystyle n!=n\times (n-1)\times (n-2)\times\cdots\times 2\times 1$ (2)

となる.また,$ 0!=1$ となっている.これらのことから,漸化式は

$\displaystyle n!$ $\displaystyle =n\times(n-1)!$ (3)
$\displaystyle 0!$ $\displaystyle =1$ (4)

と表すことができる.

ここで,整数を入力して,その階乗を計算するプログラムを作ってみよう.通常は,式 (2)の通りにプログラムを書くだろう.この式の通りにプログラムを 書くと,リスト3のようになる.

同じ計算を,式(3)と(4)に着目してプログ ラムを作ってみよう.すると,リスト4のようになる.このプログラム を見ると,漸化式をそのままプログラムしたことが分かるだろう.

リスト4のプログラムは,リスト3とは異なり, 関数内で自分自身を呼びだしている.このように,自分自身を呼び出すことを再帰呼び出 し(recursive call)と言う.C言語ではこのように自分自身を呼び出すことができる.

これまでの例で,再帰呼び出しは繰り返し文と似ていることが分かっただろう.繰り返し 文では,無限ループにならないように,必ず終了条件が必要であった.同じように,再帰 呼び出しでも,呼び出しの終了条件が絶対に必要である.そうしないと,無限に関数を呼 び出すことになり,いずれはプログラムがクラッシュするであろう.

もうひとつ重要なことは,再帰呼び出しが出きるようなアルゴリズムを考えなくてはなら ない.一つの考え方は,漸化式を書いてみることである.数学の漸化式のような考え方が できれば,それを忠実にプログラムすれば,再帰呼び出しができるであろう.

   1 #include <stdio.h>
   2 
   3 /*=====================================================*/
   4 /*  階乗を計算する関数                                    */
   5 /*=====================================================*/
   6 int kaijyo(int n){
   7   int i, value;
   8   
   9   value=1;
  10 
  11   for(i=n; i>=1; i--){
  12     value*=i;
  13   }
  14 
  15   return value;
  16 
  17 }
  18 
  19 /*=====================================================*/
  20 /*  メイン関数                                    */
  21 /*=====================================================*/
  22 int main(){
  23   int n;
  24 
  25   printf("階乗を計算します.値を入れてください\n");
  26   scanf("%d",&n);
  27 
  28   printf("%d!=%d\n",n,kaijyo(n));
  29 
  30   return 0;
  31 }

   1 #include <stdio.h>
   2 
   3 /*=====================================================*/
   4 /*  階乗を計算する関数                                    */
   5 /*=====================================================*/
   6 int kaijyo(int n){
   7 
   8   if(n==0){
   9     return 1;
  10   }else{
  11     return n*kaijyo(n-1);
  12   }
  13 
  14 }
  15 
  16 /*=====================================================*/
  17 /*  メイン関数                                    */
  18 /*=====================================================*/
  19 int main(){
  20   int n;
  21 
  22   printf("階乗を計算します.値を入れてください\n");
  23   scanf("%d",&n);
  24 
  25   printf("%d!=%d\n",n,kaijyo(n));
  26 
  27   return 0;
  28 }

3.2 練習問題

[1]
次に示す数列(フィボナッチ数列)の$ F_7$ の値は,いくつか?.値のみなら ず,計算過程も示せ.

  $\displaystyle F_k=F_{k-1}+F_{k-2}$   $\displaystyle F_0=0$   $\displaystyle F_1=1$    

[2]
フィボナッチ数列を計算するための,再帰呼び出しを使った関数を作 成せよ.
[3]
$ n$ の階乗3を再帰呼び出しで計算するた めの関数$ F(n)$ を以下に示すが, =0pt =0.4pt \fbox{\hspace{5mm} \hspace{5mm}} の内容を選択肢から選べ.

  $\displaystyle F(0)=1$   $\displaystyle F(n)=$ =0pt =0.4pt \fbox{\hspace{5mm} \hspace{5mm}}      

選択肢

  $\displaystyle F(n)\times F(n-1)$   $\displaystyle F(n-1)\times F(n-2)$      
  $\displaystyle n\times F(n-1)$   $\displaystyle (n-1)\times F(n)$      

[4]
$ n$ の階乗を計算するための,再帰呼び出しを使った関数を作成せよ.

ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
2006-02-27


no counter