Upload
hiro-yoshioka
View
411
Download
0
Embed Size (px)
DESCRIPTION
プログラミング入門、アルゴリズム
Citation preview
Copyright 2008 Hiro Yoshioka All r ights reserved 1
セキュリティ&プログラミングキャンプ2008
プログラミング入門2アルゴリズムとデータ構造
ミラクル・リナックス株式会社よしおかひろたか
Contents
• はじめに• アルゴリズムとは
はじめに• アルゴリズムとは
– 問題を解くための手順を定式化して表現したもの
– コンピュータにアルゴリズムを指示するための命令をプログラムという
アルゴリズムの例
• ユークリッドの互除法二つの自然数の最大公約数を求める– 入力をm,n (m ≧ n)– n =0 なら、 m を出力して終了– n が m を割り切るなら、 n を出力して終了– m を n で割った余りを新たに m とし、更に m と n
を取り替えて、一つ前に戻る。
プログラムの例#include<stdio.h>int main(void){ int m, n, tmp;
scanf("%d %d", &m, &n); if(m < 0 || n < 0){ puts("Error"); return 1; } while(n){ tmp = m % n; m = n; n = tmp; } printf("%d\n", m); return 0;}
なぜアルゴリズムを学ぶのか
• 優れた先達の知恵がある– 優れたアルゴリズムはシンプルで美しい
• 優れたアルゴリズムとは何かを学ぶため– 優れたアルゴリズムもそうでないアルゴリズムもあ
る??– アルゴリズムの解析
アルゴリズムとデータ構造
• 優れたアルゴリズムやデータ構造を利用すれば、問題をあっという間に解けてしまう場合がある。– どんなことが解明されているかを調べてみなけれ
ばならない。– さもないと、優れた手法が存在するのに、自己流
の下手なやり方を考案するのに時間を無駄にする。
– 自己流のアルゴリズムは• 開発に時間がかかって• 実行時間も遅くて• バグも多く、拡張性も低い
アルゴリズムとデータ構造
• アルゴリズムとデータ構造をまったく新たに考案しなければならないということはめったにない。
• 基本的なアルゴリズムとデータ構造の組み合わせで、多くの問題は解ける。
基本的なアルゴリズムとデータ構造
• 検索• ソーティング(並べ替え)• O記法• リスト• ツリー• ハッシュテーブル
参考文献:プログラミング作法、Kernighan & Pike
検索
• 配列:静的な表形式のデータを格納する• 逐次検索:個々の要素を順番に調べていって
希望の要素かどうか調べる
/* lookup: 配列中の単語を逐次検索する */int lookup(char *word, char *array[]){ int i; for (i = 0; array[i] != NULL; i++) if (strcmp(word, array[i]) == 0) return i; return 1;}
検索
• 逐次検索:特徴– データ量が少ないときには十分高速– 実装例:strchr, strstr– 作業量(実行時間):データ量に比例
• データ量が倍になれば検索時間も倍
検索
• 二分検索– 表のデータがソート(小さい順に並んでいる)され
ていると仮定する。– まず真ん中の要素を調べて、その値が自分が探し
ている値より大きかったら前半を調べ、小さければ後半を調べる。
–辞書を引くようなもの。justはquiteより前にあって、actuallyより後ろにある。
actually, ... , just, ... , quite, ... , really, ... , zeta
二分検索
int binary_lookup(char *name, char *array[], int ntab){ int low, high, mid, cmp; low = 0; high = ntab 1; while (low <= high) { mid = (low + high) / 2; cmp = strcmp(name, array[mid]); if (cmp < 0)
high = mid 1; else if (cmp > 0)
low = mid + 1; else
return mid; } return 1;}
検索
• 二分検索– 作業量:データ量のlog2(n)に比例
• 作業量の比較– 1000個のデータの比較
• 逐次検索:最大1000回• 二分検索:最大約10回
– 100万個のデータの比較• 逐次検索:最大100万回• 二分検索:最大約20回
ソーティング
• ソーティング:レコードの集まりをキーの値の大小関係によって並べ替えること。
• アルゴリズムの例– 配列の要素を1個選択する(ピボット)– その他の要素を2つのグループに分割する
• ピボット値より小さい「チビ」• ピボット値より大きいか等しい「デカ」
– 個々のグループを上記のアルゴリズムでソートする
ソーティングvoid quicksort(int v[], int n){ int i, last; if (n <= 1) return; swap(v, 0, rand() % n); last = 0; for (i = 1; i < n; i++) if (v[i] < v[0]) swap(v, ++last, i); swap(v, 0, last); quicksort(v, last); quicksort(v+last+1, nlast1);}
void swap(int v[], int i, int j){ int temp; temp = v[i]; v[i] = v[j]; v[j] = temp;}
O記法
• O記法:計算量(実行時間)を入力のサイズnの関数で表現する。
• 例:入力に含まれる要素数nによって、特定のアルゴリズムによって処理される作業量を表す。例えば、逐次検索の作業量はnに比例するし、二分検索の作業量はlog2(n)に比例する。この時、逐次検索はO(n)のアルゴリズムであると言う。二分検索はO(log2(n))のアルゴリズムである。
O記法
• 記法 名称 アルゴリズム例• O(1) 定数 配列インデックス• O(log(n)) 対数 二分検索• O(n) 1次 文字列比較• O(nlog(n)) nlog(n) クイックソート• O(n²) 2次 単純なソート• O(n³) 3次 行列乗算
• O(2n) 指数 集合分割問題
リスト
ヘッド
データ データ データ データ データ
NULL
ポインタ
• 単一リンクリスト:データと次の項目へのポインタを含んでいる項目の集合
• サイズ:– 配列:固定長– リスト:可変長
配列とリスト
ヘッド
データ データ データ データ データ
NULL
ポインタ
• 順序の変更– 配列:ブロック移動– リスト:ポインタのつけかえ
• 項目の追加(サイズの変更)– 配列:通常は静的なサイズなのでできない– リスト:項目の追加、削除は容易
リスト
name: データ
next: NULL
typedef struct Name Name;struct Name { Name *next; char *name;};
Name *newitem(char *name){ Name *newp;
newp = (Name *) malloc(sizeof(Name)); if (newp == NULL) exit(2); newp>next = NULL; newp>name = name; return newp;}
リスト:先頭に追加
Name *addfront(Name *listp, Name *newp){ newp>next = listp; return newp;}/* 使用例 */nvlist = addfront(nvlist, newitem("smiley"));
name:”smiley”
next: NULL
nvlist
name:”smiley”
next: NULLnvlist
①
②
③
NULL
nvlist NULL
リストの検索
Name *lookup(Name *listp, char *name){ for ( ; listp != NULL; listp = listp>next) if (strcmp(name, listp>name) == 0) return listp; return NULL;}
ツリー
• 二分木
ハッシュテーブル
• 要素数Nの配列を用意し、キーの値を元に、0からN-1までの値を取る関数(ハッシュ関数)によってレコード(キーと値のペア)を格納する。
出典:Wikipedia:ハッシュテーブル
まとめ
• 様々なアルゴリズムがある。• 使えそうなアルゴリズムとデータ構造を選択し
よう。• 配列、リスト、ツリー、ハッシュテーブルが基本だ。
参考文献
• プログラミング作法、Braian W. Kernighan, Rob Pike, ISBN 4-7561-3649-4