400 likes | 540 Vues
アルゴリズムとデータ構造 Ⅰ 及び演習. 担当 講義部分:阿部圭一 演習部分:小西達裕 TA (相澤 直人、 伊藤 大輔). 厳しい! 「プログラミング」でわからなかったことを 放っておかないように。. この授業に関するホームページ. http://edu.cs.inf.shizuoka.ac.jp/2005/X121 昨年度の資料は http://edu.cs.inf.shizuoka.ac.jp/2004/T020. 2005 年度スケジュール(暫定). 2005 年度スケジュール(つづき). 今日の疑問.
E N D
アルゴリズムとデータ構造Ⅰ及び演習 担当 講義部分:阿部圭一 演習部分:小西達裕 TA(相澤 直人、 伊藤 大輔) 厳しい! 「プログラミング」でわからなかったことを 放っておかないように。
この授業に関するホームページ http://edu.cs.inf.shizuoka.ac.jp/2005/X121 昨年度の資料は http://edu.cs.inf.shizuoka.ac.jp/2004/T020
今日の疑問 1.アルゴリズムって何だろう? なぜ、アルゴリズムについて勉強するの? 2.アルゴリズムとデータ構造とは どういう関係があるのだろう?
ソフト・サービス化 製品のソフト化 内蔵ソフトウェア ステップ 120万 ソフトウェア・テストケース ケース 約7万
1.アルゴリズムとは p.2 処理の手順を記述したもの →厳密な定義 「計算モデルとアルゴリズム」 (3年後期) プログラムとどう違う? アルゴリズムはプログラム言語で 書かなくてよい
普通の順序 アルゴリズム(とデータ構造)を考える ↓ プログラムを書く アルゴリズム=プログラム ?
C言語を習得したら、プログラムが書けるか?C言語を習得したら、プログラムが書けるか? たとえ話: 英会話を習得したら、英語で話せるか? 囲碁のルールがわかったら、囲碁が 上手に打てるようになるか?
あなた方の目標 × ○ プログラムが書ける 良いプログラムが書ける そのためには 1.アルゴリズムとデータ構造 2.プログラミング技術 この授業では、1を主、2を従 2→「プログラミング方法論」に続く
教科書 p.3 先頭 プログラムを書く(プログラミング)という 行動は、 ①プログラムの仕様の決定 ②プログラムの設計 ③コーディング 「プログラミング」の授業で得られたのは 主として③の知識と技術 ②:この授業 ①→「システム要求分析設計」
N.Wirthの有名な本:「アルゴリズム+データ構造=プログラム」N.Wirthの有名な本:「アルゴリズム+データ構造=プログラム」 なぜか? →この授業を聞けばわかる 以下、とりあえず省略 → p.6 1.3へ
1.3 なぜアルゴリズムを勉強するのか? 著者の回答 1.好奇心 2.プログラミング技術の向上 でも、待てよ? プログラムの再利用は最近の流れ ↓ すでにあるプログラムはブラックボックスで よい? 利用できればいいんだ!?
高い 安い できる仕事の範囲 基本部品の中味を 知っているプログラマ 基本部品の中味を 知らないプログラマ
教科書 p.7 中央付近 ブラックボックス化が進むからこそ、 アルゴリズムに関する深い知識が 必要とされる 同じことをするのに、複数のアルゴリズムが 存在する → アルゴリズムの選択 アルゴリズムの性能を知っていなければならない 平均的なふるまい、最良/最悪の場合 ↓ アルゴリズムの中味を知っていなければならない
もう一つの論点(教科書には書いていない) 基本的な部品を組み合わせるだけで 適切なアルゴリズムが作れるか? NO! ↓ 自分で適切なアルゴリズムとデータ構造を 作り出す能力が必要 ↓ 既存のアルゴリズムとデータ構造を学ぶ ことにより、培われる
プログラムを書く学習 vs. プログラムを読む学習 (良い) ↓ ここに、問題あり! 世の中にあるプログラミングの本の かなりの割合はお勧めできない。 この教科書のプログラムはまあまあ良いが、 構造化、プログラム書法に問題あり。
次の疑問 1.計算量って何だろう? どういう意味があるの? 2.探索とは? 線形探索と二分探索
2.2.1 線形探索法による探索の計算量p.112.2.1 線形探索法による探索の計算量p.11 2.1 後回し 2.2 後回し 表の探索(表引き)という問題: 次のスライド 解法(アルゴリズム): ・線形探索
線形探索法のプログラム p.12List 2.1 struct { int key; int data; } table[100]; int n; /* table に登録されているデータの個数 */ int search( int key ) { int i; i = 0; while ( i < n ) { if ( tabel[i].key == key ) return ( table[i].data ); /* 見つかった */ i++; } return -1; /* 見つからなかった */ } 構造体変数の宣言のしかた struct { メンバの変数宣言; メンバの変数宣言; : } 構造体変数; ↑ この例では、ここが配列 tabel[100] もう一つの方法: typedef struct { メンバの変数宣言; メンバの変数宣言; : } 型名; 型名 変数, 変数, ・・・; 配列もよくわかってないんです けど・・・。 おいおい、そこまで戻っていると この授業が進まないから、演習 の時間に個人授業を。
番兵 (sentinel) 87 別解(プリント講#2参照) 87を探す 三浦宏之
2.2.2 二分探索法による探索の計算量 疑問: もっと速い方法はないか? 辞書を引くときにあなたはどうするか? 表の探索(表引き)という問題: 解法(アルゴリズム): ・線形探索 p.12List 2.1 ・二分探索 p.16List 2.2
二分探索法の過程 p.17Fig. 2.1 探すキーの値は 14とする。 a[0]=1 a[1]=3 a[2]=4 a[3]=8 a[4]=13 a[5]=14 a[6]=18 a[7]=20 a[8]=21 a[9]=25 low→ a[0]=1 a[1]=3 a[2]=4 a[3]=8 a[4]=13 a[5]=14 a[6]=18 a[7]=20 a[8]=21 a[9]=25 a[0]=1 a[1]=3 a[2]=4 a[3]=8 a[4]=13 a[5]=14 a[6]=18 a[7]=20 a[8]=21 a[9]=25 middle→ <14 =14 low→ low, middle→ high→ >14 middle→ high→ high→
二分探索法のプログラム p.16List 2.2 struct { int key; int data; } table[100]; int n; /* table に登録されているデータの個数 */ int binary_search ( int key ) { int low, high, middle low = 0; high = n-1; while ( low <= high ) { middle = ( low + high ) / 2; if ( key == table[middle].key ) return ( tabel[middle].data ); /* 見つかった */ else if ( key < tabel[middle].key ) high = middle – 1; else /* key > tabel[middle].key である */ low = middle + 1; } return (-1); /* 見つからなかった */ }
線形探索と二分探索について,なお理解不足ならば線形探索と二分探索について,なお理解不足ならば http://www.kayoo.org/home/mext/joho-kiki/ →ソフトウェア→検索のアルゴリズム
前回の復習 • アルゴリズムとは何か なぜアルゴリズムとデータ構造を学ぶのか • 表の探索(表引き) ・線形探索 ・二分探索
今日の疑問 1.計算量って何だろう? なぜ計算量という考え方をするの? 2.スタックってどういうデータ構造だろう? 配列を使ってスタックを作るには?
2.2 計算量 p.10 あるアルゴリズムはどのくらい速いか? つまり、計算速度(計算時間)は? ↓ コンピュータ、OS、言語、コンパイラ、 コンパイラのオプションに依存する ↓ 計算の手数(必要な基本演算の数)が データの個数nに対してどのように増えるか?
計算量とは(つづき) O(nの関数)の形で表す このとき、定数係数は無視する オーダーという オーダーが違う オーダーが1桁違う
定数係数は無視する O(1) (p.14 先頭) O(log n) O(n) O(n log n) O(n2 ) O(n3 ) 多項式オーダー ・・・ O(2n) 指数関数的
計算量の性質 O(f(n))+O(g(n))=O(max{f(n),g(n)}) p.13 O(f(n))・O(g(n))=O(f(n)・g(n)) p.14
線形探索の計算量(比較の回数)は 最良1、最悪n、平均(n+1)/2 データ数nに対して O(n) 二分探索の計算量(比較の回数)は 2k-1≦n<2kのとき k回 つまり、データ数nに対して 約O(log2n) logの底は何でもかまわない (理由) log2n=log210・log10n ↑ 定数係数
線形探索の計算量は O(n) 二分探索の計算量は O(log n) n=1,000だったら? n=1,000 log2n=約10 (なぜなら210=1,024) 100倍違う! 定数係数が少しくらい違ったって、 勝負は明らか!
データの登録も考えると p.18~ 登録(n要素当り) 探索(1回当り) 線形探索 O(n) O(n) 二分探索 O(n2) O(log n) クイックソートで O(n log n)
二分探索法の過程 p.17Fig. 2.1 探すキーの値は 14 とする。 a[0]=1 a[1]=3 a[2]=4 a[3]=8 a[4]=13 a[5]=14 a[6]=18 a[7]=20 a[8]=21 a[9]=25 low→ a[0]=1 a[1]=3 a[2]=4 a[3]=8 a[4]=13 a[5]=14 a[6]=18 a[7]=20 a[8]=21 a[9]=25 a[0]=1 a[1]=3 a[2]=4 a[3]=8 a[4]=13 a[5]=14 a[6]=18 a[7]=20 a[8]=21 a[9]=25 middle→ <14 =14 low→ low, middle→ high→ >14 middle→ high→ high→
登録1回あたりの検索の回数をSとすると、 線形探索 O(n)+S・O(n) 二分探索 O(n log n)+S・O(log n) n<<Sでないと、二分探索は有利に ならない! 頻繁にデータ集合が変わるような応用には 二分探索は適さない →では、どうする?
p.23 下から1/4 一般に,プログラムの実行速度を上げるには ①速いマシンに乗り換える ②高性能なコンパイラでコンパイルする ③頻繁に実行される部分をアセンブラで 記述するなどして高速にする これらの手段はいずれも定数係数を小さくする だけ! 計算量のオーダーは改善されない 効率の悪いアルゴリズムを選んだら終わり!