回 2-7 道 2 データ構造とアルゴリズム
ハッシュテーブルは、
読み終えたら衝突が
この頁の流れ
鍵から
名前から 電話番号を、 端から 探さずに引けるか
引けます。
端から
ハッシュテーブルは、
ただし、
ハッシュテーブルは どう動くのか
ハッシュテーブルは、
鍵から ハッシュ値、 ハッシュ値から入れ場所
ハッシュテーブルの
- ハッシュ関数で、
鍵を ハッシュ値 (整数) に変える - ハッシュ値を
バケツの 数で 割り、 余りを バケツの 番号にする
Python では hash() が
ハッシュ値の
衝突は 避けられない
別の
鍵の
| 扱い方 | 衝突したとき | 探すとき |
|---|---|---|
| チェイン法 (つなぐ) | 同じ | その列を |
| オープンアドレス法 | 決まった | 同じ順で、 |
どちらでも、
詰まり 具合と広げ直し
詰まり
詰まり
Java の HashMap の
Python の dict と set も ハッシュテーブル
Python の dict (辞書) と set (集合) は、
公式文書のdict のset も
| 探し方 | 前提 | 1 件を探す手間 |
|---|---|---|
| 線形探索 | なし | O(n) |
| 二分探索 | 並んでいる | O(log n) |
| ハッシュテーブル | 鍵がばらける | 平均 O(1)、 |
動かして確かめる
1 本目は、
動かす バケツ 8 個のハッシュテーブル
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
hash(12) 12
0 []
1 [33, 41]
2 []
3 []
4 [12, 20, 28, 4]
5 []
6 []
7 [7]
get 33 (330, 1)
get 7 (70, 1)
get 4 (40, 4)
get 36 (None, 4)hash(12) は
33 と
2 本目は、
動かす 詰まり具合と比べた回数
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
2000 0.5 1.236 4
1000 1.0 1.483 5
500 2.0 1.965 7
250 4.0 2.983 12
125 8.0 4.987 18詰まり
衝突が 重なると、 なぜ 遅くなるのか
全部の
次のdict に== (__eq__) が
動かす 全部同じハッシュ値の鍵
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
250 0 31125 31125
500 0 124750 124750
1000 0 499500 499500ハッシュ値が== は
全部同じだと、
外の
ハッシュテーブルは 仕事で どう 確かめるのか
仕事では、言語の dict や set を
- 「すでに
あるか」を 何度も 聞くなら、 端から比べる listではなくsetやdictを使う - 自分で
__hash__を書いた 型は、 違う 鍵が 違う ハッシュ値に なるかを 試験で見る - 鍵が
外から 来るなら、 受け取る 件数に 上限を 置く (次の 節の PHP の max_input_vars) - ハッシュ値を
外から 読めない 言語の 版を 使う。 Python 3.3 から 文字列の ハッシュ値は 起動ごとに変わる
データベースの
面接のdict で
動かす 合計が目標になる 2 つ
▶ 実行ボタンを押すと結果がここに表示されます
実行すると、次の通りに出ます
[0, 1]
[1, 3]
None
[0, 1]目標 22 は[1, 3] です。None で、
関わる実例
ハッシュの 衝突を 狙って Web サーバーを 止める HashDoS (2011年12月28日)
2011年12月28日、
同じ
Web の
各言語の
- PHP は
CVE-2011-4885 です。 2012年1月10日の 5.3.9 で、 受け取る 引数の 数の上限 max_input_varsが足されました。 公式文書の 既定の 値は 1000 です - Python は
CVE-2012-1150 です。 2.6.8、 2.7.3、 3.1.5、 3.2.3 で、 文字列の ハッシュ値に 起動ごとの 乱数を 混ぜる 「ハッシュの ランダム化」が -Rで使えるようになりました。 辞書の 並び順に 頼る コードが 多いため、 既定は 切ってありました - Python 3.3 から、
ハッシュの ランダム化は 既定で 有効です。 値を 固定したい ときは 環境変数 PYTHONHASHSEEDに数を入れます - 混ぜた
乱数を 外から 割り出せると 示され、 PEP 456 (Python 3.4) で 文字列の ハッシュ関数を、 秘密の 値を 持つ SipHash に 替えました
崩れた
出典は oCERT-2011-003 (oCERT) と 28C3 の
よくある問い
HashMap や 連想配列と ハッシュテーブルは 違う ものですか
連想配列はHashMap もdict も、
チェイン法と オープンアドレス法は どちらが 良いのですか
詰まり
パスワードを 守る ハッシュと 同じ ものですか
同じhash() の
Python の dict は 入れた 順を 覚えていますか
覚えています。set の
確認クイズ
答えだと
1 問目
ハッシュテーブルで、
2 問目
この
バケツごとに数える
d = {}
for k in [5, 13, 21, 2]:
i = k % 8
d[i] = d.get(i, 0) + 1
print(d)3 問目
全部の
4 問目
2011年12月に
説明課題
ハッシュテーブルで
自分の
この回の 先の一歩
辞書や
もっと深く
この
一次資料
どれも
- oCERT-2011-003 (oCERT、英語)。告知の
日、 対象、 CPU を 100% 使う こと、 Perl の 弱点と 同じ こと、 Python の 直った 版、 Credit の 欄の 報告者が Alexander Klink と Julian Waelde であること - 28C3 の
発表 4680 (Chaos Computer Club、英語)。発表の 日、 題、 発表者、 1 回の 要求で CPU を 使わせられること - CVE-2011-4885 と CVE-2012-1150 (NVD、
英語)。対象の版 - PHP 5 ChangeLog と php.ini の設定 (php.net、
英語)。 5.3.9 で max_input_varsが足された こと、 既定の 値 1000 - Command line and environment と 2.7 版 (Python 公式文書、英語)。
-RとPYTHONHASHSEED、辞書を作る 最悪が O(n²) な こと、 既定で 切って あった理由 - Data model, object.__hash__ (Python 公式文書、英語)。3.3 から
既定で 有効なこと、 hash()の幅 - PEP 456 (python.org、英語)。Python 3.4 で
SipHash にした理由 - Design and History FAQ と Time complexity (Python 公式文書、
英語)。 辞書が ハッシュテーブルである こと、 平均 O(1) と 最悪 O(n) - Built-in Types (Python 公式文書、英語)。整数の
ハッシュ値、 辞書が 入れた 順を保つこと - HashMap (Java SE 21 公式文書、英語)。既定の
詰まり 具合 0.75 と、 およそ 2 倍への広げ直し - Index Types (PostgreSQL 公式文書、英語)。ハッシュの
索引が 等しいの 比べだけを扱うこと
次へ
道 2 データ構造とアルゴリズムの回
- 2-0アルゴリズムとは順次、
分岐、 反復の 3 つで書く手順頁で読む - 2-1線形探索と二分探索100 万件でも
20 回で見つかる頁で読む - 2-2バブルソートと
挿入・選択ソート遅い ソート 3 つ、 2 倍で 約 4 倍頁で読む - 2-3クイックソートと
マージソート速い ソート 2 つ、 平均と最悪頁で読む - 2-4スタックとキュー積む順と並ぶ順頁で読む
- 2-5再帰自分を
呼んで 小さくする頁で読む - 2-6木と
二分探索木たどる 順、片寄り頁で読む - 2-7ハッシュテーブル鍵から
一気に 引く、衝突この回 - 2-8ダイクストラ法と最短経路点と
線、 幅優先、 重みのある道頁で読む - 2-9動的計画法同じ
計算を 2 度しない頁で読む - 2-10試験と
面接で確かめる基本情報 科目B、 道場 10 問、 面接 20 問頁で読む
