応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回...

52
応用プログラミング 高瀬 裕(たかせ ゆたか) [email protected] http://iui.ci.seikei.ac.jp/~takase/ 応用プログラミング<6> 第十三回 2014/12/17

Transcript of 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回...

Page 1: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

応用プログラミング

高瀬 裕(たかせ ゆたか)[email protected] http://iui.ci.seikei.ac.jp/~takase/

応用プログラミング<6> 第十三回 2014/12/17

Page 2: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

授業日程・内容回数 日程 内容 テキスト第1回 9/24 基本データ型, 制御構造 1章第2回 10/1 一次配列,string クラス 2章 3章第3回 10/8 関数定義とスコープ (Vector型) 4章(5章)第4回 10/15 ファイル操作 6章第5回 10/22 テキスト入力処理 7章第6回 10/29 ポインタの基本 8章第7回 11/5 配列とポインタ 9章第8回 11/12 中間試験第9回 11/19 多次元配列 10章第10回 11/26 構造体 11章第11回 12/3 関数宣言, 関数名の多重定義, デフォルト引数, 関数テンプレート 12章第12回 12/10 再帰呼び出し 13章第13回 12/17 アルゴリズム 14章第14回 1/14 配列を用いた間接参照 15章第15回 1/21 期末試験

Page 3: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

前回の復習

Page 4: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

再帰呼び出し

Page 5: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

再帰呼び出しとは関数の中で自身を呼ぶことです

関数が自分自身を呼び出すこと

再帰呼び出し(recursive)

void func(){

    ~~ 処理 ~~

func();

~~ 処理 ~~ };

func() 関数が その処理の中で func() 関数(自身)を呼び出す

適切に使うと記述が簡単になります

Page 6: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

無限ループ単純に考えると無限ループしますね

int recursive(){

   cout << “出力” << endl; recursive();

return 0; };

int main(){

recursive(); }

 自分自身を呼び出す。 呼び出し続けて終わらない。 (実際には関数の呼び出しでメモリを 消費していくのでメモリを使い果たして 異常終了するはずです。)

上手に止めてあげれば 役に立ちます

再帰呼び出しは止め方を最初に考えます

Page 7: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

階乗の計算(p117)再帰呼び出し

int rec_fact(int n){

if( n == 0 ) return 1; return n * rec_fact(n-1);

};

n=0 で ストップ

n* rec_fect(n-1)main関数

int main (){ rec_fact(5);

}

実行結果 120

確かに結果は正しいです。 どのような処理手順か 想像つきますか?

Page 8: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

再帰呼び出しの処理順序一度最後まで辿り、戻ってくるn * rec_fact(4)

return 5 * 24

n*rec_fact(3)

return 4 * 6

n*rec_fact(2)

return 3 * 2

n*rec_fact(1)

return 2 * 1

n*rec_fact(0)

rec_fact(5)

rec_fact(4)

rec_fact(3)

rec_fact(2)

rec_fact(1)

n = 0 なので再帰終了!! return 1

rec_fact(0)

return 1return 1 * 1

return 2 * 1return 3 * 2

return 4 * 6return 5 * 24

start!!

中間地点

 goal

次々に処理の途中で呼び出す

終了条件に合致したら 順番に処理が終了していく

Page 9: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

再帰呼び出しは自己ループではないwhile文のようなループとは異なります

while(true)    cout << “出力” << endl; };

int recursive(){

   cout << “出力” << endl; recursive();

return 0; };

whileループは この文の先頭に戻ります

再帰呼び出しは 自分で自分自身(と 全く同じ関数)呼び出す呼び出した関数が終われば 自分も終わります。

次々に関数を呼んでいき、最後に呼ばれたものから終了していく。(メモリが必要な理由がここにあります。)

Page 10: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

再帰呼び出しと局所変数(p119)新たな関数が呼び出され、最後から順に終了していきます

void recur( int n){ int x = n*n;

cout << n << “:” << x << “(before)” << endl;

if( n < 0 ) return; // これが終了条件

recur(n -1);

cout << n << “:” << x << “(after)” << endl; }

int main(){recur(3); return 0;}

3:9(before) 2:4(before) 1:1(before) 0:0(before) -1:1(before) 0:0(after) 1:1(after) 2:4(after) 3:9(after)

after の出力は再帰呼び出しが最後まで到達してから始まる

Page 11: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

再帰呼び出しと局所変数呼び出しの順番

n =3; x= 9; before(3)文の出力

after(3)文の出力

n =2;x= 4; before(2)文の出力

after(2)文の出力

n =1;x= 2; before(1)文の出力

after(1)文の出力

n =0;x= 0; before(0)文の出力

after(0)文の出力

n =-1;x= 1; before(-1)文の出力 ここで再帰終了!!

次々に引数や局所変数の 異なる関数が呼び出される

nが負だと after文は 呼ばれない

start!!

中間地点

Goal

最初の n や x が保持されていますが 処理の途中で関数を呼んでるので当然です

r e c u r (3)

r e c u r (2)

r e c u r (2)

r e c u r (1)

recur(-1)

Page 12: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

入力と逆順の出力(p120)複数の文字列を入力し、逆から出力

void recur_print( ){ string s; if( cin >> s){ // これが終了条件 recur_print();

} cout << s << endl;

}

int main(){ recur_print();

return 0; }

if( cin >> s)入力が成功する : true 失敗(EOF等) : false終了条件として成立します

cout がいつ実行されるか もうわかりますよね

次々に関数を呼んで入力を要求し続け、 入力が失敗したら最後から出力されるはずです

Page 13: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

練習問題出力を書いて下さい

実験の復習です。 出力を書いてみましょう

rec(6)

rec(4)

rec(2)

rec(0)return;

cout << 2;

rec(0)return;

return;

・ ・ ・ ・

最初の方は→

Page 14: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

rec(6)

rec(4)

rec(2)

rec(0)return; (rec0)

cout << 2;

return; (rec2)

cout << 4;

rec(0)return; (rec0)

rec(2)

rec(0)return; (rec0)

cout << 2;

return; (rec2)

rec(0)return; (rec0)

return; (rec4)

cout << 6;

rec(4)

rec(2)

rec(0)return; (rec0)

cout << 2;

return; (rec2)

cout << 4;

rec(0)return; (rec0)

rec(2)

rec(0)return; (rec0)

cout << 2;

return; (rec2)

rec(0)return; (rec0)

return; (rec4)

return;(rec6)

Page 15: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

アルゴリズム

Page 16: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

アルゴリズムアルゴリズムって何だ

ある処理を行うための手続きや手段,手順のこと

バブルソートのアルゴリズムってのをやりました?

今日は有名なアルゴリズムをお伝えします。 (手順を覚えておけばプログラムにできますよ)

Page 17: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

探索法配列から目的のものを手早く探す

A B C D E F G H I J例えば、上記配列から G のカードの位置を求めたいなら

逐次探索法

2分探索法

端から 1 枚ずつ見ていきます。

もう少し効率的に見ていきます。

Page 18: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

逐次探索法アルゴリズム端から見ていく

A B C D E F G H I J★ ★ ★ ★ ★ ★ ★ ★ ★ ★

裏返したとして

これをプログラムできればいいわけです。

0

A B C D E F G H I J★ ★ ★ ★ ★ ★ ★ ★ ★1A B C D E F G H I J★ ★ ★ ★ ★ ★ ★ ★2A B C D E F G H I J★ ★ ★ ★ ★ ★ ★3A B C D E F G H I J★ ★ ★ ★ ★ ★4

A B C D E F G H I J★ ★ ★ ★ ★5A B C D E F G H I J★ ★ ★ ★6A B C D E F G H I J★ ★ ★7

ここで終了

Page 19: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

逐次探索法の実装端から見ていく

int main(){ const int size = 10000; int a[size] = {}; for(int i =0; i < size; i++){ a[i] = i;

}

const int x = 5000;

for(int i =0; i < size; i++){ if( a[i] == x) break;

}

cout << i << endl; return 0; }

10個や20個ではすぐ終わるので 10000個の配列を作ります

5000を見つけてストップする

Page 20: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

処理時間の計測時間を計測できると便利です。

#include<ctime>時間計測のためにインクルード

clock_t start = clock(); 計測したい処理

clock_t end = clock(); cout << (double)(end-start)/CLOCKS_PER_SEC<<endl;

計測したい処理に掛かった時間が表示できる。

Page 21: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

#include<iostream> #include<ctime>

using namespace std;

int main(){ const int size = 10000; int a[size] = {}; for(int i =0; i < size; i++){ a[i] = i;

}

const int x = 5000; clock_t start = clock(); for(int i =0; i < size; i++){ if( a[i] == x) break;

} clock_t end = clock(); cout << i << endl; cout << (double)(start - end)/CLOCLS_PRE_SEC << endl; return 0; }

Page 22: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

2分探索法アルゴリズム楽になる気がしますよ

アルファベット順に並んでいる仮定 :

特定のカードがどこにいるかわからないが 少なくとも並び順が決まっているなら

2分探索アルゴリズムで手早く済ませられます

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★アルファベット順に並んだカードから P を探してみます

Page 23: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

2分探索法アルゴリズム探索領域を半分にしていく

1:中央のカードをめくる

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★ ★ ★

2:条件判定

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★ ★ ★

P > O なのでこのカードより左側には存在しない。 見る必要のないカード

めくる = Pかどうか調べる探索開始位置 探索終了位置

中央

Page 24: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

3:残りの中央をめくる

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★ ★

2分探索法アルゴリズム続き探索領域を半分にしていく

探索終了区間

4:条件判定

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★ ★探索終了区間

P < U なのでUより右には存在しない 見る必要なし

探索開始位置 探索終了位置

中央

探索開始位置が移動 = 中央も変化

Page 25: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

2分探索法アルゴリズム続き探索領域を半分にしていく

5:のこりの中央をめくる

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★探索終了区間 探索終了区間

6:条件判定

C G I K L O P S U W X★ ★ ★ ★ ★ ★ ★ ★探索終了区間 探索終了区間

P == P なので残りを見ないで終了!

探索開始 位置

探索終了 位置

中央

探索終了位置が移動 = 中央も変化

Page 26: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

2分探索法アルゴリズムの実装アルゴリズムからコードへ

中央のカードをめくる 条件判定を行う 探索領域が半分に減る(開始位置 or 終了位置が変化)

の繰り返しでした。

比較的単純なループ処理で実装できそうです。

当然ですが、英文字とカードという例でなくても 並び順が分かっている配列であれば このアルゴリズムで探索可能です。

Page 27: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

2分探索法アルゴリズムの実装アルゴリズムからコードへ

int main(){

const int size = 11; const char a [size] = {‘C’, ‘G’, ‘I’, ‘K’, ‘L’, ‘O’, ‘P’, ’S’, ‘U’, ‘W’, ‘X’};

char x = ‘P’; // 探したい文字

cout << x << “は配列の中に”; if( binarySearch(a, size, x)) cout << “ あります”; else cout << “ありません”;

cout << endl;

binarySearch() 関数には 配列(の先頭要素のアドレス),要素数,探索文字を渡し bool で戻ってくることがわかる

Page 28: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

bool binarySearch(const char a[], int sz, char x){

bool found = false;

int first = 0; // 探索開始位置 int last = sz - 1; // 探索終了位置

while( first <= last ) { int middle = (first + last) / 2; // 中央の位置

if(a[middle] == x){ found = true; break;

}

if(a[middle] < x) first = middle + 1; // 現在の中央より右側にある

else // 現在の中央より左側にある last = middle - 1;

}

return found; }

結果によって探索範囲が狭まる。

見つけたら終了

小数点は無視して問題ない

中央値より小: 探索開始位置が変化 中央値より大: 探索終了位置が変化

Page 29: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

練習問題2分探索の実装

void が戻り値の 2分探索アルゴリズムを実装しましょう 見つけられなかった場合の処理もいれましょう。

Page 30: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

ソート自分で並べる

2分探索法を行うためには 並び順が分かっている 必要 がありました。

自分である法則に従って並び変えるのがソートアルゴリズムです。

選択ソートバブルソート

今回紹介遅い 実装楽遅い 実装楽速い 実装難

Page 31: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

バブルソート2つずつ比較するのを繰り返す

14 78 3

14 78 3

14 78 3

14 78 3

隣の相手と比較して順番を入れ替える1周目

14 78 3

14 78 3

1478 3

14 78 3

最小値確定2周目

1周目終了

Page 32: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

1478 3

9 2周目終了

1478 3

1478 3

10

1478 3

11

ソート完了

3周目終了

4周目終了

比較が10回入れ替えは 場合による

1478 3 1周終了で1つ確定する3周目

12 1478 3

134周目

14

5周目1478 315

実際は 4周終われば ソート終了としてよい

周回が進むと 比較回数が減っていく

Page 33: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

バブルソートの実装例えばこう

for(int i=0; i <size -1; i++){ // 最後のループは比較・交換の必要なし for(int j =0; j<size -1 -i; j++){ // ループが進むにつれて確定していくので比較対象が減る if(mn[j] < mn[j+1]) // 隣と比較

// これは入れ替え関数 swap(mn[j],mn[j+1]); } }

Page 34: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

選択ソート

14 78 3

降順に並べ変えます

1. 先頭を最大と仮定して   より大きい物を探す

14 78 3

3. 最大と先頭を入れ替える1 4 78 3

1 4 78 34. 最大は求まり,配列の先頭。   次から繰り返えせばよい

2. 大きいのを見つけたら それと残りを比較

最大(最小)を見つけて入れ替える

Page 35: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

1478 3

1 4 78 3

1 4 78 3

1478 3

1478 3

1478 3 ソート完了

同じ位置に入れ替えた。

比較が10回入れ替えは最大4回

Page 36: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

選択ソートの実装例えばこう

int j; for(int i=0; i <size -1; i++){ // 一番最後は比較・交換の必要なし int m = i; // ループの開始を最大と仮定 for(j =i+1; j<size; j++){ // 残りを比較していく if(mn[m] < mn[j]) //より大きければ m = j;  // その後の基準を変更 } // 配列の最後まで最大のものを探し続ける

// 現在の先頭と最大値を入れ替え swap(mn[i],mn[m]); }

Page 37: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

その他のソート例マージソート

Page 38: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

その他のソート例クイックソート

Page 39: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

標準アルゴリズムの利用当然あらかじめ用意されています

#include <algorithm>を使うと、予め用意されたアルゴリズムが利用可能

min();max();swap();

sort();関数テンプレートで紹介

binary_search();find();

今回紹介

これらを標準アルゴリズム(の一部)といいます。

Page 40: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

標準アルゴリズムでの配列範囲指定配列の範囲は 先頭 から 末尾+1 まで

標準アルゴリズムの関数に配列型データを渡す場合 配列の範囲を指定する。(配列全部か一部か選べる)

例 : 配列のソート int a[size] size = 5a[0] a[1] a[2] a[3] a[4]

完全ソート sort(&a[0] , &a[size]);

部分ソート sort(&a[1] , &a[4]);

先頭要素のアドレスと末尾の次の要素のアドレスを渡す

345 12a[5]

存在しない a[5] のアドレスを渡す

a[1] から a[3] までのソート

Page 41: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

sort() の例何でも昇順にソートする!

#include<iostream> #include<algorithm> using namespace std;

int main(){ const int size = 5; int a[size] = {5, 3, 2, 7, 2};

sort(&a[0], &a[size]);

for(int i = 0; i < size; i++){ cout << a[i] << ‘ ’;

cout << endl; return 0;

}

ヘッダファイルのインクルード

0 から 最後尾+1 = size

Page 42: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

ソートしてから2分探索2分探索には独自の関数を使います。

#include<iostream> #include<algorithm> using namespace std; // binarySearch関数は次のページ int main(){ const int size = 11; char a[size] = {‘Z’, ‘G’, ‘K’, ‘Y’, ’T’, ‘P’, ’S’, ‘C’, ‘I’, ‘X’}; sort(&a[0], &a[size]);

char x; while( cin >> x){

if(binarySearch(a, size, x)) cout << x << is found. << endl; else cout << x << is not found. << endl;

} return 0;

}

ソート(先頭と最後の要素+1を渡す) 今回は char 型

先程作った2分探索関数を呼ぶ

Page 43: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

bool binarySearch(const char a[], int sz, char x){

bool found = false;

int first = 0; // 探索開始位置 int last = sz - 1; // 探索終了位置

while( first <= last ) { int middle = (first + last) / 2; // 中央の位置

if(a[middle] == x){ found = true; break;

}

if(a[middle] < x) first = middle + 1; // 現在の中央より右側にある

else // 現在の中央より左側にある last = middle - 1;

}

return found; }

結果によって探索範囲が狭まる。

見つけたら終了

小数点は無視して問題ない

中央値より小: 探索開始位置が変化 中央値より大: 探索終了位置が変化

Page 44: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

標準アルゴリズムによる2分探索binary_search()

binary_search(先頭アドレス, 要素数+1のアドレス, 探索対象);

与えられた配列内に探索対象があれば true を返す (bool が戻り値)

自分で関数を作成する必要が無くなる。 sort()と同様に組込型(int とか charとか)に全体対応

double型のような実数型で誤差が生じる場合は注意

Page 45: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

#include<iostream> #include<algorithm> using namespace std; int main(){ const int size = 11; int a[size] = {‘Z’, ‘G’, ‘K’, ‘Y’, ’T’, ‘P’, ’S’, ‘C’, ‘I’, ‘X’}; sort(&a[0], &a[size]);

char x; while( cin >> x){

if(binary_search(&a[0],&a[size], x)) cout << x << is found. << endl; else cout << x << is not found. << endl;

} return 0;

}

binary_search()による2分探索これで完結

引数の渡し方に注意

Page 46: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

標準アルゴリズムによる逐次探索find()

find(先頭アドレス, 要素数+1のアドレス, 探索対象);

与えられた配列内に探索対象があれば 対象要素のアドレスを返す

探索対象がなければ 第二引数のアドレスを返す

探索する配列の最後の要素 + 1 のアドレス

逐次探索させてみましょう

Page 47: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

#include <iostream>#include <algorithm>

using namespace std; int main() {

const int size = 11; const char a[size] = {’Z’, ’G’, ’W’, ’K’, ’Y’, ’T’, ’P’, ’S’, ’C’, ’I’, ’X’}; char x; while (cin >> x) { if (find(&a[0], &a[size] , x) != &a[size]) {

cout << x << " is found in the array a[]." << endl;

}else{

cout << x << " is not found." << endl; }return 0;

}

逐次探索例find()の引数と戻り値に注意

第二引数が戻ってこないなら

速度を調べてみましょう

Page 48: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

練習問題選択ソートとfind()

選択ソートを実装しましょう。 また、標準アルゴリズムを使ってみましょう

Page 49: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

binary_search() と find()どっち使います?

探索という意味では binary_search() の方が速いです

しかし、一旦 sort() を呼ぶ必要があるなら 結果として find() を使って端から調べたほうがいい場合もあります。

あらかじめ並び順が決まっているなら binary_search() それ以外だとケースバイケースといった所でしょうか

Page 50: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

実験の諸注意注目!

口頭試問を受けたら僕宛にメールで Source Codeを送って下さい。(実行結果は必要ないです) [email protected]

座席は前から 3, 4列目 で変わらず。 問1 問2 が終了したら一旦呼んで下さい。

ソースにコメントを入れてから呼ぶこと コメントがないと受け付けません。

Page 51: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

実験問題の軽い説明

Page 52: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...第十三回 2014/12/17 授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型,

問3 の難関は構造体の作成でしょう

読み取った文字列 (string ) は 1文字目がカードのマーク (mark) 2文字目がカード番号(num)の10の位 3文字目がカード番号(numの1の位

構造体を作ってしまえば,2回ソートするうち どちらを先にやるか選べるようにしなさいという問題です。