これは,実際にプログラムを示した方がよく分かるので,以降に簡単な例を示す.
| (1) |
ここで,整数を入力して,その階乗を計算するプログラムを作ってみよう.通常は,式 (2)の通りにプログラムを書くだろう.この式の通りにプログラムを 書くと,リスト1のようになる.
同じ計算を,式(3)と(4)に着目してプログ ラムを作ってみよう.すると,リスト2のようになる.このプログラム を見ると,漸化式をそのままプログラムしたことが分かるだろう.
リスト2のプログラムは,リスト1とは異なり, 関数内で自分自身を呼びだしている.このように,自分自身を呼び出すことを再帰呼び出 し(recursive call)と言う.C言語ではこのように自分自身を呼び出すことができるので ある.
今回の例の場合,再帰呼び出しを使うメリットはほとんど無い.実行速度も繰り返し文を
使うリスト1の方が速いだろうし,メモリーの消費も少ない.し
かし,次のハノイの塔のプログラムになると,再帰呼び出しを使うと,簡潔なプログラム
が書ける.ここの例題の階乗の計算では,再帰呼び出しのアルゴリズムの大体のイメージ
がつかめれば良い.
1 #include <stdio.h>
2
3 /*=====================================================*/
4 /* 階乗を計算する関数 */
5 /*=====================================================*/
6 int kaijyo(int n){
7 int i, value;
8
9 value=1;
10
11 for(i=n; i>=1; i--){
12 value*=i;
13 }
14
15 return value;
16
17 }
18
19 /*=====================================================*/
20 /* メイン関数 */
21 /*=====================================================*/
22 int main(){
23 int n;
24
25 printf("階乗を計算します.値を入れてください\n");
26 scanf("%d",&n);
27
28 printf("%d!=%d\n",n,kaijyo(n));
29
30 return 0;
31 }
1 #include <stdio.h>
2
3 /*=====================================================*/
4 /* 階乗を計算する関数 */
5 /*=====================================================*/
6 int kaijyo(int n){
7
8 if(n==0){
9 return 1;
10 }else{
11 return n*kaijyo(n-1);
12 }
13
14 }
15
16 /*=====================================================*/
17 /* メイン関数 */
18 /*=====================================================*/
19 int main(){
20 int n;
21
22 printf("階乗を計算します.値を入れてください\n");
23 scanf("%d",&n);
24
25 printf("%d!=%d\n",n,kaijyo(n));
26
27 return 0;
28 }
世界の中心の地・ベレナスに,天高くそびえる3本のダイヤモンドの柱.そのうち1本に は,64枚の黄金の円盤が刺さっている.向かって左側の柱だ.一番下のものがもっとも大 きく,上に行くにしたがって円盤は小さくなっていく.そうして積み重ねられた64枚の円 盤.これを3つのルールに従って移動していく.
そうして右の柱にすべての円盤を移したとき,世界は崩壊し,その終焉を迎えるだろう.日夜,インドの坊主たちが塔から塔へ円盤を移動させているのである.これが,世界の終 わりの時を刻んでいるというから驚きである.
64枚の円盤を移動させるのは大変なので,3枚の円盤を移動させてみよう.それは,図 3のようになる.
このパズルを解くということは,円盤の移動の手順を示すことである.図 3の左端に書かれている円盤の移動元と移動先を示せれば良い.この手 順をすべて示して,左端にある円盤を右端に移動させるのである.
これを一つずつ考えていたのではとてもプログラムはできない.次にようにすれば,この パズルが完成することが分かるだろう.塔を便宜上,移動元(from),作業用(work),移動 先(to)に分ける.
これを,階乗を計算したときの漸化式のように記述すると,
| (5) |
このアルゴリズムをプログラムで記述したものが,リスト3である.この アルゴリズムとリスト3,および図3を考えよ.
1 #include <stdio.h>
2
3 /*=====================================================*/
4 /* ハノイの塔の移動を示す関数 */
5 /*=====================================================*/
6 void move(int n, char from, char work, char to){
7
8 if(n==1){
9 printf("%c -> %c\n", from, to);
10 }else{
11 move(n-1, from, to, work);
12 printf("%c -> %c\n", from, to);
13 move(n-1,work, from, to);
14 }
15 }
16
17 /*=====================================================*/
18 /* メイン関数 */
19 /*=====================================================*/
20 int main(){
21 int n;
22
23 printf("ハノイの塔の円盤の枚数を入力してください\n");
24 scanf("%d",&n);
25
26 move(n, 'A', 'B', 'C');
27
28 return 0;
29 }
1 void QuickSort(int bottom,int top,int *data)
2 {
3 int lower,upper,div,temp;
4 if(bottom>=top)
5 return;
6 /* 先頭の値を「適当な値」とする */
7 div=data[bottom];
8 for(lower=bottom,upper=top;lower<upper;)
9 {
10 while(lower<=upper&&data[lower]<=div)
11 lower++;
12 while(lower<=upper&&data[upper]>div)
13 upper--;
14 if(lower<upper)
15 {
16 temp=data[lower];
17 data[lower]=data[upper];
18 data[upper]=temp;
19 }
20 }
21 /* 最初に選択した値を中央に移動する */
22 temp=data[bottom];
23 data[bottom]=data[upper];
24 data[upper]=temp;
25
26 QuickSort(bottom,upper-1,data); /* 数列の前半について,再帰呼び出し */
27 QuickSort(upper+1,top,data); /* 数列の後半について,再帰呼び出し */
28 }
[転載について]
このペー
ジ中のリスト4のプロ
グラムは,教科書として使用している以下の書籍
| 書名 | プログラミングの宝箱 アルゴリズムとデータ構造 ISBN4-7973-2419-8 |
| 著作者 | 紀平拓男・春日伸弥 |
| 出版社 | ソフトバンク パブリッシング株式会社 |