データ構造とアルゴリズム

第十回 (2014年11月 28日)

ハッシュ関数とハッシュ法

http://www.sw.it.aoyama.ac.jp/2014/DA/lecture10.html

Martin J. Dürst

AGU

© 2009-14 Martin J. Dürst 青山学院大学

目次

辞書のこれまでの実装の計算量

方法 探索 挿入 削除
整列済み配列 O(log n) O(n) O(n)
整列無し配列・連結リスト O(n) O(1) O(n)
平衡木 O(log n) O(log n) O(log n)

直接アドレス表

(direct addressing)

問題点: 配列の大きさ

解決案: キーの変換

 

ハッシュ法の概要

(hashing, scatter storage technique, 挽き混ぜ法など)

問題点 1: ハッシュ関数の設計

問題点 2: 激突対策

 

ハッシュ関数の概要

(hash function)

2. は単純なので 1. に注目 (1.だけを「ハッシュ関数」という場合が多い)

ハッシュ関数の具体例 1

(SDBM ハッシュ関数)

int sdbm_hash(char key[])
{
    int hash = 0;
    while (*key) {
        hash = *key++ + hash<<6 + hash<<16 - hash;
    }
}

 

ハッシュ関数の具体例 2

(実例ではない; MurmurHash3 参照; 32ビット用)

#define ROTL32(n,by) (((n)<<(by)) | ((n)>>(32-(by))))
int too_simple_hash(int key[], int length)
{
    int h = 0;
    for (int i=0; i<length; i++) {
        int k = key[i] * C1;  // C1 は定数
        h ^= ROTL32(k, R1);  // R1 は定数
    }
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    return h;
}

 

ハッシュ関数の評価

 

ハッシュ関数の注意点

 

特殊なハッシュ関数

 

暗号技術的ハッシュ関数

(cryptographic hash function)

 

激突の問題と対応

 

激突対策の用語・変数

チェイン法

(chaining, 連鎖法)

 

チェイン法の実装

 

開番地法

(open addressing, オープン法)

ハッシュ表の探索・挿入・削除の計算量

チェイン法の場合、平均

 

ハッシュ表の拡大・縮小

 

拡大の計算量の分析

(償却分析 (amortized analysis) の簡単な一例)

 

ハッシュ法の評価

利点:

問題点:

 

辞書の実装の比較

方法 探索 挿入 削除 整列
整列済み配列 O(log n) O(n) O(n) O(n)
整列無し配列・連結リスト O(n) O(1) O(1) O(n log n)
平衡木 O(log n) O(log n) O(log n) O(n)
ハッシュ表 O(1) O(1) O(1) O(n log n)

 

Ruby の Hash クラス

(Perl: hash; Java: HashMap; Python: dict)

 

Ruby でのハッシュの実装

 

今回のまとめ