再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1...

5
再帰アルゴリズム 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+...+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 は不要。 6

Upload: others

Post on 09-Jul-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 再帰アルゴリズム 例 - u-toyama.ac.jp2.考え方 1)終了条件:n=1 ならば,その 1 枚を A から B に移動 2)n>1ならば, i.B を退避場所として使い,A

再帰アルゴリズム

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

例: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

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

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

課題6. 配列を使わない ack を JS で実装し, ack(3,2)

を求めよ。[ファイル名を 5-7.html とせよ。] 7. 配列を使う ack を JS で実装し, ack(3,2) を求

めよ。[ファイル名を 5-8.html とせよ。]

25