[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

コンピュータIIIB(Javaアルゴリズム)第4回

目次 索引
4.1 再帰
4.1.1 再帰とは
4.1.2 再帰呼出しの仕組み
4.1.3 再帰的プログラムの例
4.2 演習4
4.3 レポート課題
4.4 参考文献
階乗  グレイ符号  再帰的関数  再帰的手続き  再帰的プログラム  再帰呼出し  ハノイの塔問題  フィボナッチ数 

4.1 再帰

4.1.1 再帰とは

再帰とは、自分自身を呼び出すことです。 もちろん、ただ呼び出したのでは、無限ループに陥ってしまいます。 if文などを使い、ある条件のもとで自分を呼び出すのです。 再帰は、問題の種類によっては分かりやすい解決方法になります。

再帰的プログラムrecursive program

再帰呼出しrecursive call

再帰的手続きrecursive procedure

再帰的関数recursive function

はじめに、 n の階乗を計算します。 ここで、 n階乗factorial )とは、1から n までの積のことです。 これを、再帰を使って

fact(n) = n * fact(n - 1), fact(0) = 1

と定義します。

/*  1*/ class Factorial {
/*  2*/     public static void main (String[] args) {
/*  3*/         System.out.println("fact(3) is " + fact(3));
/*  4*/         System.out.println("fact(4) is " + fact(4));
/*  5*/         System.out.println("fact(5) is " + fact(5));
/*  6*/     }
/*  7*/     static int fact (int n) {
/*  8*/         if (n == 0) {
/*  9*/             return 1;
/* 10*/         } else {
/* 11*/             return n * fact(n - 1);
/* 12*/         }
/* 13*/     }
/* 14*/ }
b04a001@AsiaA1:~/comp3b% java Factorial
fact(3) is 6
fact(4) is 24
fact(5) is 120
b04a001@AsiaA1:~/comp3b%

4.1.2 再帰呼出しの仕組み

4.1.3 再帰的プログラムの例

再帰的プログラムの例として、フィボナッチ数を取り上げます。 フィボナッチ数Fibonacci number )とは、

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

のように、1, 1 から始め、直前の2つの数を足して次の数にするという数列です。 この規則は、

fib(n) = fib(n - 1) + fib(n - 2), fib(0) = fib(1) = 1

のように再帰を使って定義できます。 この定義をそのままプログラムにしますと、フィボナッチ数の計算ができるのです。

/*  1*/ class Fibonacci {
/*  2*/     public static void main (String[] args) {
/*  3*/         System.out.println("fib(3) is " + fib(3));
/*  4*/         System.out.println("fib(4) is " + fib(4));
/*  5*/         System.out.println("fib(5) is " + fib(5));
/*  6*/     }
/*  7*/     static int fib (int n) {
/*  8*/         if (n <= 1) {
/*  9*/             return 1;
/* 10*/         } else {
/* 11*/             return fib(n - 1) + fib(n - 2);
/* 12*/         }
/* 13*/     }
/* 14*/ }
b04a001@AsiaA1:~/comp3b% java Fibonacci
fib(3) is 3
fib(4) is 5
fib(5) is 8
b04a001@AsiaA1:~/comp3b%

次の例として、ハノイの塔問題を取り上げます。 ハノイの塔問題tower of Hanoi problem )とは、大きさのすべて異なる n 枚の円盤が台Aに積み上がっているとき、台Bを利用して、すべての円盤を台Cに移動するという問題です。 ただし、円盤は一度に一枚しか移動できず、小さい円盤の上に大きい円盤はのせられません。

例えば、円盤が3枚ですと、初期状態は

       +---+
       |   |
     +-+---+-+
     |       |
   +-+-------+-+
   |           |
---+-----------+---  -------------------  -------------------
         A                    B                    C

であり、最終状態は

                                                 +---+
                                                 |   |
                                               +-+---+-+
                                               |       |
                                             +-+-------+-+
                                             |           |
-------------------  -------------------  ---+-----------+---
         A                    B                    C

です。

この問題は、次のように再帰を使って解決できます。

  1. n - 1 枚を、台 x から台 z を利用して台 y に移動する。
  2. 残った1枚を、台 x から台 z に移動する。
  3. n - 1 枚を、台 y から台 x を利用して台 z に移動する。

ただし、 n が正でないときは何もしません。

n が3の場合は次のようになります。

       +---+
       |   |
     +-+---+-+
     |       |
   +-+-------+-+
   |           |
---+-----------+---  -------------------  -------------------
         A                    B                    C


                            +---+
                            |   |
   +-----------+          +-+---+-+
   |           |          |       |
---+-----------+---  -----+-------+-----  -------------------
         A                    B                    C


                            +---+
                            |   |
                          +-+---+-+          +-----------+
                          |       |          |           |
-------------------  -----+-------+-----  ---+-----------+---
         A                    B                    C
                                                 +---+
                                                 |   |
                                               +-+---+-+
                                               |       |
                                             +-+-------+-+
                                             |           |
-------------------  -------------------  ---+-----------+---
         A                    B                    C

再帰メソッドの名前は hanoi とします。 引数は、台の文字を表す x , y , z と枚数を表す n です。

/*  1*/ class HanoiTower {
/*  2*/     public static void main (String[] args) {
/*  3*/         hanoi('A', 'B', 'C', 4);
/*  4*/     }
/*  5*/     static void hanoi (char x, char y, char z, int n) {
/*  6*/         if (n > 0) {
/*  7*/             hanoi(x, z, y, n - 1);
/*  8*/             System.out.println(x + " to " + z);
/*  9*/             hanoi(y, x, z, n - 1);
/* 10*/         }
/* 11*/     }
/* 12*/ }
b04a001@AsiaA1:~/comp3b% java HanoiTower
A to B
A to C
B to C
A to B
C to A
C to B
A to B
A to C
B to C
B to A
C to A
B to C
A to B
A to C
B to C
b04a001@AsiaA1:~/comp3b%

4.2 演習4

4桁のグレイ符号を表示するプログラムを作成してください。

ここで、 n 桁の グレイ符号Gray code )とは、0と1からなる n 桁の符号を縦に2の n 乗個並べたものです。 この2の n 乗個の符号はすべて異なり、直接上下する符号は1桁のみ異なります。

グレイ符号を構成するには、次にどの桁を反転するかのみ決定するとできます。 ここで、桁を反転するとは、0を1にすることと、1を0にすることです。 例えば、3桁のグレイ符号は、次のように^で示した桁を反転させるとできます。

0   0   0
^
1   0   0
    ^
1   1   0
^
0   1   0
        ^
0   1   1
^
1   1   1
    ^
1   0   1
^
0   0   1

ここでは、グレイ符号を配列 a に格納し、{0, 0, 0, 0} から始めることにします。 n 桁の場合の反転系列を、次のように再帰を使って決定します。

  1. n - 1 桁の場合の反転系列を実行する。
  2. a [ n - 1] を反転し、配列 a の要素を表示する。
  3. n - 1 桁の場合の反転系列を実行する。

ただし、 n が正でないときは何もしません。

再帰メソッドの名前は gray とします。 引数は、配列型の a と桁数を表す n です。

なお、最初の符号0000は、再帰呼出しの前に出力しておいてください。

b04a001@AsiaA1:~/comp3b% java GrayCode
0000
1000
1100
0100
0110
1110
1010
0010
0011
1011
1111
0111
0101
1101
1001
0001
b04a001@AsiaA1:~/comp3b%

4.3 レポート課題

今日の演習4の答案をkonishi@twcu.ac.jpあてにメールで送ってください。 メールには、学生番号、氏名、科目名、授業日(10月15日)を明記してください。


4.4 参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2004年10月15日更新
konishi@twcu.ac.jp
Copyright (C) 2004 Zenjiro Konishi. All rights reserved.