・ とそれに対応する を、インデックス(索引)で管理する
・データ操作
・検索、追加、更新、削除
・データ操作は、データの 一定時間[ ]で可能
・ に対して何らかの を行う
→演算結果がキーに対するインデックス(索引)の値になればよい
「 」
…通常、非負整数(≧0)
ハッシュ法
・ハッシュ関数により得られたハッシュ値によって、ハッシュテーブルを参照する
ところで…
・ハッシュと聞いて、何をイメージしますか?
・ハッシュドポテト、ハッシュドビーフ、…
・食べ物以外にも、
・そもそもハッシュとは
・細かく切り刻む、粉々にする、細切れにする、または、その断片
・情報科学でいうハッシュ
・元データを したものを表す数値や文字列を指す用語
・元データが細切れにされ「断片」になっている、というイメージに由来
・ハッシュの持つ情報量は、元のデータより
・ハッシュ値から元データを復元することは =ハッシュの
ハッシュ関数
・キーからハッシュ値を求める関数
・ハッシュ関数に求められる性質
・ハッシュ値はハッシュテーブルの →テーブルからはみ出したらダメ
・任意のキーに対するハッシュ値の分布が になる
・これは理想…実は難しい
・現実には、異なるキーに対するハッシュ値が同じになること[ハッシュ値の ( )]は避けられない
衝突(コリジョン)対策
・発生する頻度を少なくする
・ハッシュテーブルのサイズをできるだけ する
・サイズが大きいほど、ハッシュ値のとれる範囲は拡大→衝突の確率は下がる
・テーブルを にする
・通常ハッシュ関数は、ハッシュ値を求めるのにテーブルサイズで割った を使う
…ハッシュ値がテーブルからはみ出さないようにするため
・素数で割った余りは散らばりやすい
・発生したらどうするか
・ハッシュ値を一定の規則で求め直す(再ハッシュ) …
・同一ハッシュ値のデータを同じエントリに格納する…
・同じハッシュ値を持つデータ=
オープンアドレス法

・削除の場合はちょっと注意
削除の際は、削除済みを表す印をつけておく
オープンアドレス法の性能
・1回の探索に要する平均比較回数(理想的なハッシュ関数を想定)
・再ハッシュ hash(key, i) = (hash(key, 1) + (i - 1)) % T
・探索成功 (1 - a / 2) / (1 - a)
・探索失敗 1 / 2 + 1 / (2(1 - a)^2)
aはハッシュテーブルの使用率
テーブルサイズ:T, 格納データ総数:n
a = n / T ( )
チェイン法

同じハッシュ値を持つデータ(シノニム)を、 でつなぐ
チェイン法の性能
・探索の計算量(理想的なハッシュ関数を想定)
・ハッシュ値の計算…O(1)
・シノニムが存在するとき…リストの探索が必要
・テーブルの各エントリにおける、 ( )が分かればよい
テーブルサイズ:T, 格納データ総数:n 平均何個? 個
・シノニムの探索に要する計算量…O(n/T)
・全体の計算量…O(1+n/T)
・テーブルサイズよりデータ数がずっと少ないとき(n << T)
n/T ≈ 0(ゼロ)なので、O(1+n/T)=O(1+0)=
・テーブルサイズよりデータ数がずっと多いとき (n >> T)
n/T ≈ nなので、O(1+n/T)=O(1+n)=
オープンアドレス法とチェイン法の比較
・オープンアドレス法
・実装は容易
・実用できるのは、データ数がテーブルサイズの80~90%程度まで
・データ数1000、使用率85%とすると、テーブルサイズは1200程度必要
・単純な再ハッシュはデータの塊を作りやすい
・チェイン法 … この授業で実装します
・実装は若干複雑
・実用できるのは、データ数がテーブルサイズの数倍程度まで
・データ数が1000なら、テーブルサイズは400~500程度でよい
・データ数が増えるとシノニムのリストが長くなる
チェイン法での実装(データ構造の定義)
typedef struct hash_element { //ハッシュテーブルに格納される一要素
char *key; //キー
char *value; //キーに対応する値
struct has_element *next; //次の要素(シノニム)へのポインタ
} HashElement;
typedef struct { //ハッシュテーブルはこのデータ型の配列
int count; //このエントリを共有するシノニムの数
HashElement *element; //格納する要素(キーと値)へのポインタ
} HashEntry;
HashEntry tbl[TBL_SIZE]; //TBL_SIZEはハッシュテーブルの大きさまとめ・ハッシュテーブルの特徴
・原理的には、O(1)の検索が可能
・現実には、 の作り方と、 に大きく依存する
・データに がつけられない
・順序づけが必要な場合、別途ソートが必要
・順序づけを優先したいなら、AVL木や赤黒木などの平衡二分探索木を利用
・データ格納後のテーブルサイズ変更は
・ の再ハッシュが必要
・使用場面
・ のないハッシュ関数が用意でき、十分な が使える環境での検索
・連想配列、コンパイラやインタプリタでの予約語, 変数名, 関数名等の管理