Document

2005年度
データ構造とアルゴリズム
第5回
「基本的アルゴリズム:探索」
西尾 信彦 [email protected]
立命館大学情報理工学部
情報システム学科
探索とは何か
• 多数のレコードの中から条件に合致したものを
見つけること
• 各レコードにはキーがついている
• 探す条件は,与えられたキーとの一致
–
–
–
–
学生一人につき一つのレコードがあって,
キーが生年月日で1985年1月1日が探索条件
キーが血液型でAB型Rh-が探索条件
Etc.
• ここからは,簡単のためレコードには整数が一つ
書かれていて,それがキーそのものとする
– 最初は,レコードの並びは整数型配列であるとする
逐次探索
• 頭から順にキーを比較
• 見つかる,もしくは最後のレコードまで繰替
えす
• 結果は,途中で見つかる,もしくは見つか
らない,である
etype record[RSIZE];
int search(int key) {
int i;
for (i = 0; I < RSIZE; i++) {
if (record[i] == key) return i;
}
return -1;
}
逐次探索の手間は?
• ループは何回回るのか?
– 最悪時?
– 最善時?
– 平均で?
• 比較演算は何回?
– 「番兵」を使うと比較演算を減らせる
「番兵」バージョン
etype record[RSIZE + 1];
int search(int key) {
int i = 0;
record[RSIZE] = key;
while (i != key) {
i++;
}
return i == RSIZE?-1:i;
}
• ?:は条件分岐演算子
– (項1)?(項2):(項3)
– 項1を評価(計算)して値(答え)が0でないなら項2を評
価しその値が全体の値,0ならば項3を評価した値が
全体の値となる.
もしもレコードが整列していたら...
• レコードがkeyの順(昇順,降順,辞書順な
どなんでもより)に整列していたら...
• 求めるkeyより前のデータは無視できる
– そこまで配列内を移動
• 求めるレコードが存在すべき場所でkeyを
比較
– 見つかるか見つからないかその場で決定
その場合の手間は?
• 求めるレコードが存在する場合は変らない
• 存在しない場合,平均的に半分の手間で
済む
• しかし,整列したレコードの配列を維持しな
ければならない
– 新しいレコードが来たら,途中に挿入
– 後ろのレコードを一つづつコピーしてずらす
– 逐次探索ならどこに入れても影響なし
リスト構造での探索
•
•
•
•
単方向リストの場合での逐次探索
見つかればそのレコードへのポインタが,
見つからなければNULLが返る
レコードのvalメンバにkeyが入っている
link search(list l, int key) {
for (l = l -> next; l != NULL; l = l -> next) {
if (l -> val == key) return l;
}
return NULL;
}
リストを生成するときに整列する
• 新しいレコードをリストに挿入するときに,
その場所を探索する
• 単方向リストなので一つ手前のレコードか
ら,l -> next -> valがkeyと等しいかを比べ
る
– 前に戻る手間をなくしている
自己再構成リスト
• リストは先頭にあるレコードほどアクセスす
る手間が少ない
• 一度アクセスしたレコードはリストの先頭に
つなげておく
– 「超」整理法と同じ考え方
二分探索法
• 整列したレコードに対して
– これはリストよりも配列の方がよい
• 中央に位置するレコードのキーを比べる
– 一致していれば終り,していなければ
– 前半分を探すか後ろ半分を探すか決め
– 同じことを繰り返す
• 手間はlog nに減る
– かなり劇的に減っている
内挿法
• 二分探索するときに単純に中央のレコード
は選ばない
• Keyを見てどのあたりが適切かを決めなが
ら選ぶ
• レコードのキー値が均等一様に分布してい
ることを想定
– そうでない場合には効率が下る
O記法による計算の手間の表記
• 問題の大きさをnとする
– 例えばレコードの数
• そのときにその計算の手間のオーダを見積る
• 関心はnが大きくなるとどのくらい計算が大変に
なるかにある
• O(n)という記法は問題の大きさと計算の手間が
同程度に推移するという意味
– たとえば,レコード数が100倍になったとき計算量もほ
ぼ100倍になるということ
その他の計算量
• O(1)
– 問題の大きさにかかわらず一定量の計算ですむもの
• O(log n)
– 計算をすすめるにしたがい問題の大きさが定数分の
一になっていくような計算
• O(n)
• O(n log n)
• O(n2)
– 問題の大きさが10倍になれば,それに必要な計算が
100倍(=10*10)になるような計算
練習問題
• 10個程度の整数データをリスト構造を用
いて格納し,自己再構成探索を行うプログ
ラムコードを記述せよ。できれば,実際にコ
ンパイルをし,動作を確認せよ。