フリーソフトの小道   

コンピュータ・プログラマー養成講座(入門編)

第7回 再帰プログラミングというおもしろい手法
〜管理人(志)からプログラムのヒントを差し上げようということです〜

 今回の講座で取り上げる「再帰」という言葉は、 英語では recursion または recursive といい、繰り返すなどの意味があり、 文字通り、自分自身で自分を定義するプログラムのことを言う。 数学の世界にこれと同じ仕組みのものが 「漸化式(ぜんかしき)」 といえる。 漸化式とは数列を表す表現形式で、物理でも使われることが多いものだ。
 具体的な例で示してみよう。n番目の数が、それより1つ前の数を2倍して 1 引いたものになるという。 これを漸化式で示すと  an = 2 an-1 - 1   になる。 最初の数を 1 とすると、どのような数になるのだろうか?(これは数学の一人前の問題になる)
このように、分からない数列 an を自分の数列を使って表しているやり方を見て欲しい。 プログラミングにおいてもこれと同じような手法を使ったものが再帰プログラミングという。 普通のプログラムの流れとは異なるのでプログラミング初心者には理解しづらい手法であるが、 プログラミングの中でよく使われる手法なのでここで紹介するわけだ。

 一番分かりやすい例として、階乗を計算するプログラムを紹介しよう。 階乗とは 6! という形で表されるもので、 高校生なら誰でも知っている 6!=6・5・4・3・2・1=720 のように計算する。 任意の数の階乗を計算するプログラムを作る場合、普通のプログラミング手法では次のようになる。 BASICでプログラムを作ってみよう。

100 K=1
120 FOR I=1 to N
130 K=K*I
140 NEXT I

 階乗を求めたい数を N に入れて、上のプログラムを実行すると階乗の値が計算されて K に返される。 この方法は N が定まっている場合は有効で、このプログラムは教科書的なものになっている。 しかし、繰り返しの値が不定(分からない)場合については難しいのだ(具体的な例については後述する)。
 そこで、再帰プログラミングが登場する。具体的なプログラム例を示してみよう。 ただし、旧来のBASICでは再帰プログラミングは出来ない(プログラム言語として機能が弱いので)。 なお、現在の Visual BASICなどのように、ローカル変数拡張されたBASICは再帰プログラミングは可能だが。 そこで、プログラミング言語 C を使用して説明してみよう。

int fact_func( int n ) {
  if ( n > 1 ) {
     return n*fact_func(n-1);
  }else{
     return 1;
  }
}

 上のプログラムで階乗の計算が出来ることを理解する人は少ないので、 順を追ってこのプログラムを説明してみよう。
 引数 n の値を 4 としよう。

  1. 関数の引数 n が 4 として、if 文 の判定をおこなう。
  2. 4 は 1 より大きいから、すぐ次の文 return n*fact_func(n-1) を実行する。
  3. return は関数の戻り値を示すが、その値は 4*fact_func(3) である。
  4. したがって、4 と fact_func(3) の積を戻り値なる。しかし、後ろの fact_func(3) はまだ定まらない。・・・(1)
  5. 次に、fact_func(3) を実行する(すなわち 3 の階乗)。
  6. 関数の引数 n が 3 として、if 文 の判定をおこなう。
  7. 3 は 1 より大きいから、すぐ次の文 return n*fact_func(n-1) を実行する。
  8. return は関数の戻り値を示すが、その値は 3*fact_func(2) である。
  9. したがって、3 と fact_func(2) の積を戻り値なる。しかし、後ろの fact_func(2) はまだ定まらない。・・・(2)
  10. 次に、fact_func(2) を実行する(すなわち 2 の階乗)。
  11. 関数の引数 n が 4 だから、if 文 の判定をおこなう。
  12. 2 は 1 より大きいから、すぐ次の文 return n*fact_func(n-1) を実行する。
  13. return は関数の戻り値を示すが、その値は 2*fact_func(1) である。
  14. したがって、2 と fact_func(1) の積を戻り値なる。しかし、後ろの fact_func(1) はまだ定まらない。・・・(3)
  15. 次に、fact_func(1) を実行する(すなわち 1 の階乗)。
  16. 関数の引数 n が 1 だから、if 文 の判定をおこなう。
  17. 1 は 1 より大きくないから、後ろの文 return 1 を実行する。
  18. return は関数の戻り値を示し、その値は 1 である。値は確定した。
  19. (3)の fact_func(1) が 1 になったので、2*1 が計算され、fact_func(2) の戻り値 2 が定まる。
  20. (2)の fact_func(2) が 2 になったので、3*2 が計算され、fact_func(3) の戻り値 6 が定まる。
  21. (1)の fact_func(3) が 6 になったので、4*6 が計算され、fact_func(4) の戻り値 24 が定まる。
  22. 以上で、fact_func(4) の戻り値(4の階乗の値) 24 が計算されることになる。

 この階乗のプログラムの仕組みを漸化式で示すと、an = n * an-1 と表したのと まったく同じ考えでプログラムが作られていることに気付けば、再帰プログラミングの便利さが理解できたのではないでしょうか?
 なぜ、再帰プログラミング? との疑問があるかといわれれば、「コンテストに使えるのだよ」 と答えるだけのこと。 では、どのように使うのかは自分で考えてくださいね。

2004/02/17  管理人(志)


感想・意見は、掲示板、または メールでどうぞ! --- 管理人(志)