第10講 関数の再帰的呼び出し=関数の自己再帰の学習 
第9話 グローバル変数(メンバ変数)を使用しない汎用的順列作成プログラム
解答コード例
import java.io.*;
class r{
  public static int[] x=new int[20];
  public static int n;
  public static int cn;
  public static void main(String args[]) throws IOException{
    BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
    int[] x=new int[20];
    int n;
    int cn;
    System.out.println("1からnまでの順列をすべて発生させます。");
    System.out.println("いくつまでの順列かキーボードから入力してください。");
    System.out.print ("n=");
    n=Integer.parseInt(a.readLine());
    cn=0;
    cn=f(0,n,cn,x);
    System.out.print ("順列総数=");
    System.out.print (cn);
  }
  public static int f(int g,int n,int cn,int x[]){
    int i,j,h;
    for(i=1;i<n+1;i++){
      x[g]=i;
      h=1;
      if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j]){
            h=0;
            break;
          }
        }
      }
      if(h==1){
        if(g+1<n){
          cn=f(g+1,n,cn,x);
        }
        else{
          cn++;
          for(j=0;j<n;j++){
            System.out.print(x[j]);
            System.out.print (" ");
          }
          System.out.println();
        }
      }
    }
    return(cn);
  }
}

解説
グローバル変数(正確には、クラス内全体に通用するクラスメンバ変数)を使用しないプログラムは、
頭が混乱します。
特に初心者の方は、

    cn=f(0,n,cn,x);
に大きな?マークを浮かべていますよね。
ですが、i=i+1;を思い返してください。
iに加工をしてそれを改めて、iに代入するです。
cn=f(0,n,cn,x);も同じです。
関数部分でcnの加工してその値をcnに代入しているのです。
      if(h==1){
        if(g+1<n){
          cn=f(g+1,n,cn,x);
        }
        else{
          cn++;
          for(j=0;j<n;j++){
            System.out.print(x[j]);
            System.out.print (" ");
          }
          System.out.println();
        }
      }
    }
    return(cn);
この辺も初心者の方には、大変難しいものとなっています。
cnは、常に内側の人形から値を返されます。
比喩だとかえって混乱するという方のために、
セル番号の上の番号から1つ下の番号に返されると言い直しましょうか。
セル番号が0→1→2と進んでいる間は、値を返す機会がありません。
値は、3→2や2→1などと呼び出された関数が任務を遂行して、
呼び出した関数へ戻るときにはじめて返されるのです。
はじめて3から2に戻るときは、cnは1として戻されます。
そして、そして2から3をもう一度呼び出すとき、cnは前に3を呼び出したときには0であったものが
f(3,3,1,a);
1に変身して関数を呼び出しています。
さらに、2→3となるときには、
f(3,3,2,a);となり、セル番号2の世界において再び加工されて3へと変身します。
1→2→3、3→2、2→3等を繰り返しながら、cnが徐々に大きくなっていくことがイメージできるでしょうか。
ぜひ、第6話から第8話に掛けてのトレースを参考にしながら、
cnがどのように動いていくのかをトレースしてみてください。
本サイトでそれをすると再び3,4話は投入しなければなりませんので、省略したいと思います。
というのは、1講は6話以上10話程度以下の原則を設けているからです。

関数の再帰的呼び出しを用いた普遍的汎用的な魔方陣自動生成プログラムの学習は
第13講あたりに予定していますが、早くプログラムを組んでみたい方は是非ともご自分で挑戦してみてください。

尚、第10講をもって『初心者のためのJava 入門 基礎から応用まで』の第1部は終了とさせていただきます。
第11講以降は第2部で続けられます。



第8話へ 第11講第1話へ

戻る

VB講義へ
VB講義基礎へ
vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部