2024.12.19

再帰呼び出し

再帰呼び出しとは

再帰呼び出しは、メソッドの中で、そのメソッドを呼び出すことです。リカーシブコール(recursive call)とも呼ばれます。

「木構造の探索」、「迷路の探索」、「チェス/オセロゲームなどで最善の手を見つける」などデータをたどっていくような処理や、「クイックソート」などのように処理するグループを分割していくなどの処理に有効です。

それでは、具体例でみていきましょう。

以下のメソッドは、再起呼び出しを使った1~Nの和を求めるメソッドsum( int n )です。

004
005
006
007
008
009
010
011
012
	// 1~nの和を再帰呼び出しで求める
	private static int sum( int n )
	{
		// nが1以下の場合、nを戻す
		if ( 1 >= n ) return n;

		// 再帰呼び出しで、 nと1~(n-1)の和を求める
		return n + sum( n - 1 );
	}

sumメソッドは自身のメソッドの中で、sumを呼び出しています。

010
011
		// 再帰呼び出しで、 nと1~(n-1)の和を求める
		return n + sum( n - 1 );

例えば「n = 5」の場合、「1~5の合計」は、

	「1~5の合計」 = 5 + 「1~4の合計」

と考えることができます。

同じように、「1~4の合計」、「1~3の合計」、「1~2の合計」は、

	「1~4の合計」 = 4 + 「1~3の合計」
	「1~3の合計」 = 3 + 「1~2の合計」
	「1~2の合計」 = 2 + 「1」

になります。

この考え方をメソッドにしたものがsumメソッドです。

「n = 5」のsumメソッドの呼び出しイメージは、

	sum( 5 ) = 5 + sum( 4 ) 
	sum( 4 ) = 4 + sum( 3 ) 
	sum( 3 ) = 3 + sum( 2 ) 
	sum( 2 ) = 2 + sum( 1 ) 
	sum( 1 ) = 1	← 引数がnが1の場合、sumは1を戻します。 

となります。

sum( 1 )の値が1で確定すると、sum( 2 )の値が2+1=3で確定します。

sum( 3 )~sum( 5 )も以下のように値が確定していきます。

	sum( 1 ) = 1
	sum( 2 ) = 2 + sum( 1 ) = 2 + 1 = 3
	sum( 3 ) = 3 + sum( 2 ) = 3 + 3 = 6
	sum( 4 ) = 4 + sum( 3 ) = 4 + 6 = 10
	sum( 5 ) = 5 + sum( 4 ) = 5 + 10 = 15

処理が終わるとsum( 5 )は「15」になります。

これが、再起呼び出しを使った1~Nの和の計算方法です。

再帰呼び出しのメリット・デメリット

ここでは、再帰呼び出しを使うメリットとデメリットについて記載します。

メリット

アルゴリズムによっては、ソースコードが短くなる。

アルゴリズムによっては、ソースコードが見やすくなる。

デメリット

メモリの消費量が大きい。

メソッドを呼び出すと、「引数」や「メソッドが戻るアドレス」などがスタック領域と呼ばれるメモリに配置されます。これらはメソッドが終了すると解放されます。

再帰呼び出し回数が多い場合に、スタック領域のメモリが解放されずスタックオーバーフローになることがあります。

Javaソースコード - 1~Nのを求める

再帰呼び出しを使って1からNの和を求めるJavaソースコードです。

Recursion1.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
import java.util.Scanner;

public class Recursion1 {
	// 1~nの和を再帰呼び出しで求める
	private static int sum( int n )
	{
		// nが1以下の場合、nを戻す
		if ( 1 >= n ) return n;

		// 再帰呼び出しで、 nと1~(n-1)の和を求める
		return n + sum( n - 1 );
	}

	// メイン
	public static void main( String[] args )
	{
		// Scannerを作成
		Scanner scan = new Scanner( System.in );

		// 文字数の入力
		System.out.println( "nを入力してください" );
		int n = scan.nextInt();

		// nが1以上かをチェック
		if ( 1 > n ) {
			System.out.println( "1以上のnを入力してください"  );
			return;
		}

		// 1~nの和を取得
		int result = sum( n );

		// 結果を出力
		System.out.println( "1から" + n + "の和は、" +  result  );
	}
}

コンパイル ソースコードが「ANSI」の場合

C:\talavax\javasample>javac -encoding sjis Recursion1.java

コンパイル ソースコードが「UTF-8」の場合

C:\talavax\javasample>javac Recursion1.java

実行

C:\talavax\javasample>java Recursion1

実行例(1~5の和を求める)

nを入力してください
5
1から5の和は、15

Javaソースコード - Nの階乗を求める

再帰呼び出しを使ってNの階乗を求めるJavaソースコードです。

Nの階乗 = N! = N × ( N - 1 ) × ( N - 2 ) × ( N - 3 ) × … × 1

Recursion2.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
import java.util.Scanner;

public class Recursion2 {
	// nの階乗を求める
	private static int factorial( int n )
	{
		// nが0以下の場合、1を戻す
		if ( 0 >= n ) return 1;

		// 再帰呼び出しで、 nの階乗を求める
		return n * factorial( n - 1 );
	}

	// メイン
	public static void main( String[] args )
	{
		// Scannerを作成
		Scanner scan = new Scanner( System.in );

		// 文字数の入力
		System.out.println( "nを入力してください" );
		int n = scan.nextInt();

		// nが1以上かをチェック
		if ( 1 > n ) {
			System.out.println( "1以上のnを入力してください"  );
			return;
		}

		// nの階乗を取得
		int result = factorial( n );

		// 結果を出力
		System.out.println( " nの階乗は、" +  result  );
	}
}

コンパイル ソースコードが「ANSI」の場合

C:\talavax\javasample>javac -encoding sjis Recursion2.java

コンパイル ソースコードが「UTF-8」の場合

C:\talavax\javasample>javac Recursion2.java

実行

C:\talavax\javasample>java Recursion2

実行例(5の階乗を求める)

nを入力してください
5
 nの階乗は、120

再帰呼び出しを使う処理

以下は、再帰呼び出しを使う処理についての記事です。興味のある方は参考にしてください。

配列を使ったフィボナッチ数列を出力するプログラムを作ってみませんか?

2021.03.09

ソート(並び替え)アルゴリズムの1つであるクイックソートについて詳しく解説しています。Javaのソースコード付きです。

2019.09.06

以上です。

関連コンテンツ

キーボードを使って値を入力する方法を解説しています。ソースコード付きです。

2020.08.19

キーボードを使って整数値を入力する方法を解説しています。Scannerクラスを利用しています。

2023.03.08

キーボードを使って整数値を2つ入力る方法を解説しています。Scannerクラスを利用しています。

2023.03.16

キーボードを使って入力した整数値を2乗する方法を解説しています。

2023.03.10

キーボードを使って入力した整数値の絶対値を求める方法を解説しています。

2023.03.10

キーボードを使って実数値(double)を入力する方法を解説しています。Scannerクラスを利用しています。

2023.03.09

キーボードで入力された実数の角度からsin(サイン)、cos(コサイン)を計算し、コンソール出力する方法を解説します。

2023.04.10

キーボードを使って実数値(double)を2つ入力する方法を解説しています。Scannerクラスを利用しています。

2023.03.16

キーボードで入力した整数値を配列に格納するメソッドの作り方を解説しています。

2020.08.19

条件式を判断して処理を分岐する方法を詳しく説明しています。

2023.03.20

メソッドを抜けるときに使用するreturn文について説明しています。

2020.03.20

プログラムの最初に実行されるメソッドは?

2022.12.13

プログラミングで使う変数って何?

2020.03.23

Javaのプログラムを書いてみませんか?プログラムの書き方をくわしく説明しています。

2020.03.23

「Javaソースコード」から実行可能な「オブジェクトコード」に変換する方法をくわしく説明しています。

2020.03.23

変数やクラスに格納されている値をコンソール出力する方法は?

2020.03.23

Javaのプログラムを作ってみませんか?プログラミングに必要なものの用意から実行までを説明しています。

2020.03.23

Javaの学習に役立つソースコードを多数紹介しています。是非、ご覧ください。

2022.09.10

Swingパッケージを使ってグラフィック表示を行う方法を解説しています。

2020.03.23

画像フォーマット形式・色・大きさ・傾きなどの変更、特定の図形(文字・記号など)を見つけたり、取り出したりする画像処理について詳しく解説。

2015.11.29

繰り返し処理を使ったJavaのソースコードサンプルを紹介しています。

2020.03.23

配列を使うJavaソースコードを多数紹介しています。

2021.05.18

数学に関係するJavaのメソッドやソースコードなどを紹介しています。

2022.10.25

三角形、台形、円などいろいろな図形の面積を計算するプログラムを紹介しています。詳しくは、記事をご覧ください。

2021.05.18

StringクラスとStringBuilderクラスを利用したプログラミングの仕方を紹介しています。

2016.12.16

Javaを使った簡単な応用プログラム(生年月日から年齢を計算プログラムなど)を紹介しています。

2022.07.07

プログラミング、ITに関する用語をまとめています。

2022.10.17

日本で使われてきた伝統文様「和柄」について解説しています。

2022.07.27

メソッドの定義方法を詳しく解説しています。Javaのサンプルソースコードを使った説明もあります。

2020.03.23

繰り返し処理の作り方を解説しています。

2016.03.02

ソート(並び替え)アルゴリズムの1つであるクイックソートについて詳しく解説しています。Javaのソースコード付きです。

2019.09.06

1+2+3+ … +Nを計算する公式と、その導き方を掲載しています。

2021.07.03

複数の数値の合計値と平均値を計算するプログラムをJavaのソースコードを使って解説しています。

2020.03.23

アルゴリズムって何?

2022.12.29

コンピュータは、いくつかの装置から構成されています。その主な5つの装置(機能)って何?

2022.07.10

プログラミング言語とは?種類や特徴について説明しています。

2022.08.03

「ゆるゆるプログラム」のコンテンツを紹介しています。興味のある方はこの記事をご覧ください。

2020.03.23

広告