再帰(さいき)とは、ある処理の内部で、その処理自体をもう一度呼び出すプログラミングの手法です。
例えるなら、合わせ鏡やロシアのマトリョーシカ人形のようなものです。
鏡の中に鏡が映り込み、そのまた中に鏡が映り込む…というように、同じ構造が繰り返し現れます。
目次
再帰の仕組み
再帰には、2つの重要な要素があります。
- ベースケース (Base Case): 処理を終了させるための条件です。「これ以上繰り返さないで」という停止信号の役割を果たします。マトリョーシカの一番小さい人形のように、これ以上中には何もない状態です。
- 再帰ステップ (Recursive Step): 処理自体をもう一度呼び出す部分です。問題を少しだけ簡単な形にして、未来の自分(次の呼び出し)に処理を託します。
この 2つが揃っていないと、処理が無限に繰り返されてしまい、プログラムが停止してしまいます(無限ループ)。
具体的な例:階乗の計算
例えば、「5の階乗(5! = 5 × 4 × 3 × 2 × 1)」を計算する処理を考えてみましょう。
- 5! は 5 × 4!
- 4! は 4 × 3!
- 3! は 3 × 2!
- 2! は 2 × 1!
- 1! は 1 ← これがベースケース(停止条件)です。
これをプログラムで書くと、以下のようになります。
AutoIt での再帰関数のサンプルコード
#include <MsgBoxConstants.au3>
; ### メイン処理 ###
; 階乗を計算したい数を指定します。
Local $iNumber = 5
; Factorial関数を呼び出して結果を取得します。
Local $iResult = Factorial($iNumber)
; 結果をメッセージボックスで表示します。
MsgBox($MB_OK, "階乗の計算結果", $iNumber & " の階乗は " & $iResult & " です。")
; ### 階乗を計算する再帰関数 ###
Func Factorial($n)
; ベースケース(停止条件):
; nが1以下になったら、1を返して処理を終了します。
; (1の階乗は1、0の階乗も数学的には1なので、1以下で停止させるのが一般的です)
If $n <= 1 Then
Return 1
EndIf
; 再帰ステップ:
; n と「n-1 の階乗の結果」を掛けて、その値を返します。
; 自分自身(Factorial関数)を、今より少し小さい数で呼び出しています。
Return $n * Factorial($n - 1)
EndFunc ;==>Factorial
コードの詳しい解説
Func Factorial($n) … EndFunc
Factorialという名前の関数を定義しています。この関数は、$nという一つの数値を受け取って階乗を計算します。
If $n <= 1 Then Return 1
これが*ベースケース(停止条件)です。
Factorial(5) から呼び出しが始まっても、いつかはFactorial(1) が呼び出されます。
その際に、この条件に合致し、1を返して関数の呼び出しを終了させます。
この停止条件がないと、プログラムは無限に自分自身を呼び出し続けてしまいます。
Return $n * Factorial($n – 1)
これが再帰ステップです。
例えば、Factorial(5) が呼び出されると、この行は「5 * Factorial(4) の結果」を返そうとします。
そのために Factorial(4) を呼び出し、Factorial(4) は「4 * Factorial(3) の結果」を…というように、連鎖的に自分自身を呼び出していきます。
Factorial(1)が1を返したところから、逆順に計算結果が返っていきます。
Factorial(2)は2 * Factorial(1)→2 * 1で2を返すFactorial(3)は3 * Factorial(2)→3 * 2で6を返すFactorial(4)は4 * Factorial(3)→4 * 6で24を返すFactorial(5)は5 * Factorial(4)→5 * 24で120を返す
このようにして、最終的な答えが計算されます。
再帰のメリットとデメリット
- メリット: フォルダーの階層をたどる、複雑なアルゴリズムを記述するなど、再帰的な構造を持つ問題を、直感的で簡潔なコードで表現できます。
- デメリット: 処理を何度も呼び出すため、メモリの使用量が多くなったり、処理が遅くなったりすることがあります。また、処理の流れが直感的でない場合、理解が難しいこともあります。
コメント