1 - 横浜国立大学

Download Report

Transcript 1 - 横浜国立大学

アルゴリズムとデータ構造
補足資料14-1
「ハッシュ法」
横浜国立大学
理工学部
数物・電子情報系学科
富井尚志
今日の着席位置
•
•
自分の氏名を「ローマ字」で書いてください。(大学名簿に登録したもの)
次の値に変換し、総和を計算してください。
A→ 65 B→ 66 C→ 67 D→ 68 E→69
F→ 70 G→ 71 H→ 72 I→ 73 J→74
K→ 75 L→ 76 M→ 77 N→ 78 O→79
P→ 80 Q→ 81 R→ 82 S→ 83 T→84
U→ 85 V→ 86 W→ 87 X→ 88 Y→89
Z→ 90
スペース→ 32
※ First NameとFamily Nameの間には一つスペース(32)を入れて
•
その値をこの部屋の席数Bで割った余りの番号(1~B)の席に着席してください
– 余りがゼロの場合はB番
– もし、すでに席が埋まっていたら、1を足した番号の席に着席してください
•
•
それでもまだ席が埋まっていたら、空き席にあたるまで、1を足してください
氏名から、どこに座っているか当てます!
– できれば1発で
静的データと動的データ
• 静的データ
– データの総量(件数)が変化しない
• 追加や削除がない
– 静的データを扱うデータ構造:配列
• 動的データ
– データの総量や内容が変化する
• 追加や削除が発生する
– 動的データを扱うデータ構造:線形リスト、木構造
時間計算量と空間計算量
– 時間計算量: 計算の回数や時間
– 空間計算量: 計算に必要な記憶量
– ソートの問題は、主に時間計算量を見ていた。
– 今日のテーマ:動的データを格納する際
• 探索に必要な時間計算量を一定に
– データが増えても検索が超早い
• 記憶量は犠牲に
– メモリにはゆとりが必要
探索アルゴリズム(復習)
• 与えられたキーを持つデータを見つけ出す
– データの件数nに対し、どのような時間計算量か?
• 静的データに対するデータ探索(第4回)
– 線形探索: 先頭から順番に探索→ O(n)
– 2分探索: 現在地より前か後か→ O(log n)
• ただし、あらかじめソートされている必要あり
• 配列のソート
– 単純ソート(第7回): 単純選択ソートなど → O( n2 )
– 高速ソート(第8回): クイックソートなど → O( n log n )
探索アルゴリズム
• 与えられたキーを持つデータを見つけ出す
– データの件数nに対し、どのような時間計算量か?
• 動的データに対するデータ探索
– 線形リストの探索(第11回)
• 順次探索: 先頭から順番に探索 → O(n)
– 探索木(2分木)の探索(第13回)
• 現在ノードより右か左か→ O(log n)
– ハッシュ法による探索(第14回:今回)
• ハッシュ関数で「散らして」配置 → O(1)
データ件数
O( 1 )
O(log n)
O(n)
O(n x log n)
1,000
1,000,000
1,000,000,000
1
1
1
10
20
30
1,000
1,000,000
1,000,000,000
10,000
20,000,000
30,000,000,000
2
O(n )
1,000,000
O(2n)
10300
1,000,000,000,000 1,000,000,000,000,000,000
10300,000
10300,000,000
例題
• 70人が、128個ある席の一つをそれぞれ指定さ
れて、着席します。
• 氏名を聞くだけで、席番号がわかるようにしたい。
利用者数(70)<座席数(128)<<氏名数(????超沢山)
氏名を聞けば、座っている場所がわかるようにする
例題
• 氏名を聞けば、座っている場所がわかるように
する
席番号=H(氏名)
• Hは、氏名を定義域、席番号を値域とする関数
• Hが「上手に散らす」性質の関数なら、、、
• 「探索」の必要がなくなる
(すべての席を「探索」しなくても、その人が座っている場所が
わかる)
今日の着席位置
•
•
自分の氏名を「ローマ字」で書いてください。(大学名簿に登録したもの)
key[i]
次の値に変換し、総和を計算してください。
SUM(key[i])
A→ 65 B→ 66 C→ 67 D→ 68 E→69
F→ 70 G→ 71 H→ 72 I→ 73 J→74
K→ 75 L→ 76 M→ 77 N→ 78 O→79
P→ 80 Q→ 81 R→ 82 S→ 83 T→84
U→ 85 V→ 86 W→ 87 X→ 88 Y→89
Z→ 90
スペース→ 32
※ First NameとFamily Nameの間には一つスペース(32)を入れて
•
その値をこの部屋の席数Bで割った余りの番号(1~B)の席に着席してください
– 余りがゼロの場合はB番
– もし、すでに席が埋まっていたら、1を足した番号の席に着席してください
•
•
それでもまだ席が埋まっていたら、空き席にあたるまで、1を足してください
SUM(key[i]) % B
衝突→再ハッシュ
氏名から、どこに座っているか当てます!
– できれば1発で
– 遅刻、早退にも対応可能です
追加・削除→動的データ
ハッシュ法
• n件のデータの中から、キーを指定して、同じ値
が登録されている該当データを探し出す
– スペースに十分なゆとりがある
– ハッシュ表に「散らして」上手に格納する
– 探索コスト
• 最良時: O(1) → データの件数nによらず一定
• 最悪時: O(n)
• 平均: O(1+n/B)
– Bは「バケット数」:格納する配列の要素数
– n<<BならO(1) → あらかじめ用意できる配列に十分なゆとり
ハッシュ関数、ハッシュ値
ハッシュ関数:
キー⇒インデックス(索引番号)の変換関数 H(key)
– H(key):ハッシュ値; インデックス、索引番号
– ハッシュ関数は一様に「ばらまく」関数がよい
H(key) = ORD(key) % B
– 同じハッシュ値をもつキー:衝突(collision)
• 衝突時は手順に従って別の関数を適用:再ハッシュ
ハッシュ表に対する基本操作
• 他の動的データ構造(線形リスト、木)の扱い
と同じ
– 探索
• キーを与えると、ハッシュ表の該当位置を返す
– 挿入
• キーを持つデータをハッシュ表に格納する
– 削除
• キーを持つデータをハッシュ表から削除する
衝突処理の違いによる
2種類のハッシング
• 外部ハッシュ法
– チェイン法、ダイレクトチェイニング法
– バケット個の線形リストを生成
• ハッシュ表には同じハッシュ値をもつ線形リスト(の先頭アドレス)を格納
• 衝突時はリストに追加
• 格納できる要素数に制限がない
– 格納されたデータがハッシュ表の外にある:外部ハッシュ
• 内部ハッシュ法
– オープンアドレス法、オープンアドレッシング法
– バケット個の要素を持つ配列を作成
• ハッシュ値を添え字(アドレス)とする
• 衝突時は再ハッシュ
• バケット数までの要素しか格納できない
– 格納されたデータがハッシュ表の内にある:内部ハッシュ