このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。
自分の先祖を考えると、これは、おとうさん、おかあさん、おとうさんのおと うさん、おとうさんのおかあさん……と永遠に記述しなければならなくなりま すが、これを「おとうさん、おかあさんと、おとうさんの先祖とお母さんの先 祖」と言う風に先祖を規定するのに先祖という言葉を使って規定すると形の上 では短い表現で記述できます。 これを帰納的定義といいます。
ある関数から自分自身の関数を呼び出すことを再帰と言います。 C 言語は再帰が可能なため、関数定義で帰納的定義を使用することができます。 これを使うと、短い記述で複雑な問題を解くことができます。
ある問題を解く際に、その問題を同じ性質を持つ小さい部分に分解できるとし ます。 すると、その問題を解く関数 solve は再帰処理を使うと次のように書くこと ができます。
int solve(解くべき問題 t){
if(t がもう分解できない){
t を処理;
return t の答え;
}else{
t1 = t と同じ性質を持つ小さい部分;
ans1 = solve(t1); /* 再帰 */
分解した残りと ans1 によりtの答を計算;
return t の答え;
}
}
階乗 n!=n*(n-1)*...*2*1 は n!=n*(n-1)! と右辺にも階乗を含む構造に分解 できます。 一方 0!=1 となります。 従って、プログラムは次のようになります。
int kaijo(int n){
if(n==0){
return 1;
}else{
return n*kaijo(n-1);
}
}
このプログラムを使って、 5! と 6! を求めなさい。
フィボナッチ数列とは、手前の数と、その手前の数の和を次々と求めてできる 数列です。
a0=1, a1=1 とすると、n 番目(n≧ 2)は an= an-1+ an-2 と書けます。 この時の n 番目の値を求めてみましょう。
組合せの数 nCm の求め方を考えます。 これは n 個の中から m 個を取り出す取り出し方は何通りあるかということで す。 ここで、n 個のものの中から一つのものに注目します。
従って、 nCm = n-1Cm + n-1Cm-1 が得られます。 なお、n 個のものから0 個を取る取り方や、 n 個全部を取り出す取り方はと もに 1 通りしかありません。つまり nC0 = nCn = 1 です。
この式を使って再帰的なプログラムを組み、 5C2、 20C2 を求めなさい。
ハノイの塔とは次のようなパズルです。 大きさが一回りずつ違う円盤を大きい順に下から並べます。 そして、次のルールでその円盤の山を移動させます。
以下に 3 枚での例を示します。
a | b | c | ||
---|---|---|---|---|
1 |
= == === --a-- |
--b-- |
--c-- |
|
2 |
== === --a-- |
= --b-- |
--c-- |
move 1 from a to b |
3 |
=== --a-- |
= --b-- |
== --c-- |
move 2 from a to c |
4 |
=== --a-- |
--b-- |
= == --c-- |
move 1 from b to c |
5 |
--a-- |
=== --b-- |
= == --c-- |
move 3 from a to b |
6 |
= --a-- |
=== --b-- |
== --c-- |
move 1 from c to a |
7 |
= --a-- |
== === --b-- |
--c-- |
move 2 from c to b |
8 |
--a-- |
= == === --b-- |
--c-- |
move 1 from a to b |
この解法を再帰的に考えます。 もし、hanoi(n-1,'a','b','c') が n-1 枚の円盤を a から b へ移動する解法 を出力するとします(c はもう一つの領域)。 すると、 n 枚の円盤を a から b へ移動する解法は次のように考えられます。
このようにすると hanoi(n,'a','b','c') の解法を出力します。
#include <stdio.h>
void hanoi(int n, char x, char y, char z){
if(n==1){
printf("move 1 from %c to %c\n",x,y);
return;
}else{
hanoi(n-1,x,z,y);
printf("move %d from %c to %c\n",n,x,y);
hanoi(n-1,z,y,x);
return ;
}
}
int main(void){
hanoi(3,'a','b','c');
return 0;
}
上のプログラムを動かして hanoi(3,'a','b','c') と hanoi(4,'a','b','c') の解法を求めなさい。