これは,実際にプログラムを示した方がよく分かるので,以降に簡単な例を示す.
(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 |
著作者 | 紀平拓男・春日伸弥 |
出版社 | ソフトバンク パブリッシング株式会社 |