再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1...
TRANSCRIPT
![Page 1: 再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1 枚を A から B に移動 2)n>1ならば, i.B を退避場所として使い,A](https://reader034.vdocuments.pub/reader034/viewer/2022042418/5f340a82afafab324a692939/html5/thumbnails/1.jpg)
再帰アルゴリズム
1
例1. 漸化式(2項間)
a1 = 1 an = 2 an-1 + 1 ( n>=2 )
2. 具体的な計算 a1 = 1, a2 = 2 a1+1 = 2*1+1=3, a3 = 2 a2+1 = 2*3+1 = 7,.....
3. 特徴 1) 初項が与えられている。 2) n での値を計算するのに,n-1 での値を
使う。
2
例1. 漸化式(3項間)
a1 = 1, a2 = 1,an = an-2 + an-1 ( n>=3 ) フィボナッチ数列
2. 具体的な計算a1 = 1, a2 = 1, a3 = a1+a2 = 1+1=2,a4 = a2+a3 = 1+2 = 3, a5 = a3+a4 = 2+3 = 5,..
3. 特徴 1) 初期条件が与えられている。 2) n での値を計算するのに,n-1 以下での
値を使う。
3
一般化1. 関数 f(n) :再帰的関数 1) 初期条件が与えられている。[例えば,
f(1) の値] 2) f(n) を計算するのに,f(k) (k≦n-1)を使
う。 2. 再帰的関数の計算方法:f(3)=? 3) f(3) を計算するのに,f(2)などが必要。 4) f(2) を計算するのに,f(1)=初期条件が必
要。 終了条件と呼ぶべき4
再帰的アルゴリズム
1. 再帰的アルゴリズムとは 処理手順が,自分自身を用いて定義されるようなアルゴリズムのこと。
2. 再帰的アルゴリズムで欠かせないもの 自分自身の呼び出しの終了条件
5
例:f(n)=1+2+...+n1. 考え方 1) 1+2+...+(n-1) に n を加えればよい:
つまり,f(n) = f(n-1)+n 2) f(1) = 1 ←終了条件
2. 関数 f(n) のアルゴリズムf(n){ if(n=1){ return(1);
} else{ return(f(n-1)+n);
} }
最初に終了条件の判断をする!
(注)この場合,else は不要。
6
![Page 2: 再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1 枚を A から B に移動 2)n>1ならば, i.B を退避場所として使い,A](https://reader034.vdocuments.pub/reader034/viewer/2022042418/5f340a82afafab324a692939/html5/thumbnails/2.jpg)
例:f(n)=n! (=1*2*...*n)1. 考え方 1) 1*2*...*(n-1) に n を掛ければよい:
つまり,f(n) = f(n-1)*n 2) f(1) = 1 ←終了条件
2. 関数 f(n) のアルゴリズムf(n){ if(n=1){ return(1);
} else{ return(f(n-1)*n);
} } (注)この場合,else は不要。
7
例:フィボナッチ数列1. 考え方 1) f(n) = f(n-2)+f(n-1) 2) f(1) = 1, f(2) = 1 ←終了条件
2. 関数 f(n) のアルゴリズムf(n){ if(n=1 or n=2){ return(1);
} else{ return(f(n-2)+f(n-1));
} } (注)この場合,else は不要。
8
再帰アルゴリズムの構造recursive(n){ if(自明なケース){ 自明なケースの処理; /* 終了条件*/
} else{ recurve(m) 達を用いた処理; /* m は n より"簡単" */
} }
9
再帰的アルゴリズムの特徴1. 自身の引数より”簡単”な引数を用いて,自
分自身を呼び出す 2. 自明なケースの処理(終了条件)が存在 3. 表面的には,ループ(for など)は現れな
い
10
再帰的アルゴリズム:×と○1. 再帰的アルゴリズムの短所 1) 慣れないとわかりにくい 2) 正当性・停止性の判断が難しい 3) 一般に,計算量が多くなる
2. 再帰的アルゴリズムの長所 4) 慣れると,極めて分かりやすく,使いや
すい(非常に素直にプログラムが作成出来る)
11
hanoi(n,A,B,C) :ハノイの塔1. ルール 1) 3本の柱 A, B, C と,大きさの全て
異なる n 枚の穴あき円盤がある。 2) 柱 A に n 枚の円盤が,大きいもの
を下にして重ねられている。 3) 目的:この n 枚の円盤を全て柱 B
に移動する。 4) 制限
i. 一度に 1 枚の円盤しか移動できない。 ii. 大きい円盤を小さい円盤の上には置けない。 iii. ”退避場所”として残る一本の柱を使える。
12
![Page 3: 再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1 枚を A から B に移動 2)n>1ならば, i.B を退避場所として使い,A](https://reader034.vdocuments.pub/reader034/viewer/2022042418/5f340a82afafab324a692939/html5/thumbnails/3.jpg)
2. 考え方 1) 終了条件:n=1 ならば,その 1 枚を A から B
に移動
2) n>1ならば, i. B を退避場所として使い,A から n-1 枚を C に移動。
ii. 残る1枚を,A から B に移動。 iii.A を退避場所として使い,C から n-1 枚を B に移動。
hanoi(n,A,B,C) :ハノイの塔
A B C A B C
A B C A B C A B C A B C
13
hanoi(n,A,B,C) :ハノイの塔3. 関数 hanoi(n,A,B,C)
/* n:枚数, A:出発地,B:目的地,C:退避場所 */ hanoi(n,A,B,C){ if(n=1){ A から B に1枚移動;
} else{ hanoi(n-1,A,C,B); A から B に1枚移動 ; //hanoi(1,A,B,C) hanoi(n-1,C,B,A);
} }
14
課題1. JS で hanoi(n,A,B,C) を書け。ただし,「○から
△に1枚移動」するかわりに「○ -> △」と画面に 出 力 す る も の と す る 。 さ ら に hanoi(5,”A”,”B”,”C”) を実行せよ。[ファイル名を 5-1.html とせよ。]
2. n 枚の円盤に,大きいものから順に 1,2,…,n と名前をつけておく。また,柱をA, B, C ではなく,1, 2, 3 と名付けておく。「円盤 k を p から q に移動」するときに,「k : p -> q」のように出力するようにhanoiを書き換え,n=4 の場合に実行せよ。[ファイル名を 5-2.html とせよ。]
15
引数の多い 再帰的アルゴリズム
16
gcd(a,b) : a と b の gcd1. a と b の gcd を求める。 2. 考え方 1) 終了条件:a を b で割った余り r が 0 なら,b
を返す。 2) gcd(a,b)=gcd(b,r) なので,gcd(b,r) を返す。
3. 関数 gcd(a,b) のアルゴリズムgcd(a,b){ r ← a-b*[a/b]; /* r=“a を b で割った余り” */ if(r=0){ return(b); /* r=0 なら,ここで脱出 */
} return(gcd(b,r)); /* r≠0 のときだけ実行 */
}
17
nCr : 組み合わせ関数1. n 個のものから r 個を取り出すときの,取り出し
方の個数 nCrを求める。 (n ≧ r ≧ 0) 2. 使う公式:パスカルの3角形
nCr = n-1Cr-1 + n-1Cr
3. comb(n, r): nCr を返す関数の考え方 1) 終了条件:r=0 または r=n ならば 1 を返す。 2) comb(n-1,r-1)+comb(n-1,r) を返す。
18
![Page 4: 再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1 枚を A から B に移動 2)n>1ならば, i.B を退避場所として使い,A](https://reader034.vdocuments.pub/reader034/viewer/2022042418/5f340a82afafab324a692939/html5/thumbnails/4.jpg)
nCr : 組み合わせ関数4. 関数 comb(n,r) のアルゴリズム
comb(n,r){ if(r=0 or r=n){ return(1);
} return(comb(n-1,r-1)+comb(n-1,r));
}
無駄な計算が多いことに注意無駄な計算をなくするには?
(配列の利用)
19
nCr : 組み合わせ関数5. 関数 comb(n,r) のアルゴリズム(配列の利用)
配列 ai,j の初期化(すべて null にする); comb(n,r){ if(r=0 or r=n){ return(1);
} if(an,r = null){ /* まだ計算していないなら */ an,r ← comb(n-1,r-1)+comb(n-1,r); /* 計算して記憶する */
} /* 計算されている or した値を返す */ return(an,r);
} 広い記憶領域が必要
20
課題3. 配列を使わない comb(n,r) を JS で実装し,
comb(3,2), comb(5,3) を求めよ。(注:「求めよ」というのは,画面に答を出力することを意味するものとする。)[ファイル名を 5-3.html とせよ。]
4. 配列を使う comb(n,r) [ただし, n≦5 とする]を JS で実装し,comb(3,2), comb(5,3) を求めよ。[ファイル名を 5-4.html とせよ。]
21
Ackermann 関数1. Ackermann 関数:ack(m,n)非負整数 m, n に対して,次のように定義される関数 ack(m, n) のこと:
- m=0 ならば n+1, - n=0 ならば ack(m-1, 1), - それ以外の時は,ack(m-1, ack(m, n-1))
停止性の判定が難しい!
課題 5-5:停止性を証明せよ。(紙媒体)
22
Ackermann 関数2. 疑似言語で書くと
ack(m, n){ if(m=0) return(n+1); if(n=0) return(ack(m-1, 1)); return(ack(m-1, ack(m, n-1)));
}
m, n が大きくなると,爆発的に計算量が増え,かつ,値も大きな数になる。
23
Ackermann 関数3. 実際に計算してみる。 1) ack(2,1) → 黒板 2) ack(2,3) → 宿題(紙媒体:課題5-6)
4. もう少し無駄を防ぐような工夫はできないか? ↓配列を利用して,同じものを何度も計算しないようにする。
24
![Page 5: 再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1 枚を A から B に移動 2)n>1ならば, i.B を退避場所として使い,A](https://reader034.vdocuments.pub/reader034/viewer/2022042418/5f340a82afafab324a692939/html5/thumbnails/5.jpg)
課題6. 配列を使わない ack を JS で実装し, ack(3,2)
を求めよ。[ファイル名を 5-7.html とせよ。] 7. 配列を使う ack を JS で実装し, ack(3,2) を求
めよ。[ファイル名を 5-8.html とせよ。]
25