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個程度の整数データをリスト構造を用 いて格納し,自己再構成探索を行うプログ ラムコードを記述せよ。できれば,実際にコ ンパイルをし,動作を確認せよ。
© Copyright 2024 ExpyDoc