再帰
簡単な再帰関数
今回は、再帰関数を学んでいきます。
ではまずは、次の問題を考えてみましょう。
、 とします。このとき、 を求めるプログラムを書いてください。
様々な方法が考えられます。
解法 1
この漸化式は、次のように数学的に解くことができます。
よって、この結果を使えば次のように簡単に解けます。
解法 2
他には、次のようにして のように順番に求めていくこともできます。
解法 1 のように数学的に解くことができればもちろん最も良いですが、数学的に解けないような場合は解法 2 のようにするしかなさそうです。しかし、解法 2 は漸化式の形とは少し見た目が違うため少し考えてから作らないといけません。
そのようなときに、再帰関数を使うとより簡単に書くことができます。(実は、再帰関数を使う以外の選択肢がないような場面もあります。)
実際に、この問題を再帰関数を使って解いたプログラムを見てみましょう。
このプログラムを見ると、漸化式の形そのままですね。何も考えずに簡単に作ることができます。
さらに、このプログラムをよく見ると関数の中で自身を呼び出しています。a(n)
の値を求めるために a(n - 1)
を使っています。さらに、a(n - 1)
を求めるために a(n - 2)
を使っています。これを繰り返していきますが、a(1)
は 1
とわかっているので、そこで終了します。
再帰関数の作り方をまとめると、次のようになります。
- 漸化式を立てて、自身を呼び出す。(例: )
- 初期条件の処理を別に作っておく。(例: )
再帰の定義を普通に書けば次のようになります。
再帰(さいき 英:Recursion,Recursive)は、ある物事について記述する際に、記述しているもの自体への参照が、その記述中にあらわれることをいう。 -- フリー百科事典『ウィキペディア(Wikipedia)』
しかし、再帰の性質から次のように定義が書かれることもあります(笑)
コンピューターの世界では、再帰を用いた命名もよくあります。再帰的接頭語と呼ばれます。例えば、プログラミング言語の PHP は「PHP: Hypertext Preprocessor」、GNU は「GNU's Not Unix」、WINE は「Wine Is Not an Emulator」、TikZ は「TikZ ist kein Zeichenprogramm」となっています。
再帰関数を使ったフィボナッチ数列
では、再帰を使ってもう少し難しいプログラムも作ってみましょう。
フィボナッチ数を求めるプログラムを作ってみましょう。 フィボナッチ数列()は、次のように定義されます。
次のような数列になっています。
やはり、再帰を使うと定義どおりに書けて簡単ですね。
fib
関数の流れは次のようになっています。
高校数学でやるように、フィボナッチ数列の一般項は求めることができます。ビネの公式と呼ばれます。
の 2 解を とします。すなわち、、とすれば、
です。よって、
練習問題 1
再帰関数を使って、 から までの和を求める関数を作ってみましょう。
ヒント
漸化式は、次のようになります。
練習問題 2
再帰関数を使って、最大公約数を求める関数を作ってみましょう。
さらに、その結果を用いて、最小公倍数を求める関数も作ってみましょう。
ヒント
ユークリッドの互除法を用いれば簡単にできます。
解答
練習問題 3
リュカ数を求めるプログラムを作ってみましょう。
リュカ数列()は次のように定義されます。
リュカ数列は次のようになります。
リュカ数列の一般項は、フィボナッチ数列の時のように計算すると、次のようになります。
練習問題 4
トリボナッチ数を求めるプログラムを作ってみましょう。 トリボナッチ数列()は次のように定義されます。
トリボナッチ数列は次のようになります。
ちなみに、テトラナッチ数、ペンタナッチ数、…もあります。
名称 | |
---|---|
2 | フィボナッチ数 |
3 | トリボナッチ数 |
4 | テトラナッチ数 |
5 | ペンタナッチ数 |
6 | ヘキサナッチ数 |
7 | ヘプタナッチ数 |
8 | オクタナッチ数 |
9 | ノナナッチ数 |
10 | デカナッチ数 |
11 | ウンデカナッチ数 |
12 | ドデカナッチ数 |
トリボナッチ数列の一般項は、次のようにして計算できます。
の 3 解を とすると、
とします。
から、
テトラナッチ数は、次のようになるようです。確かめてはいません。
の 4 解を とすると、