キーと値のペアを格納するための連想配列
ハッシュテーブルとしての小さな電話帳
コンピュータサイエンス において 、 ハッシュテーブルは 連想配列( 辞書 または単に マップ とも呼ばれる) を実装する データ構造 です。 連想配列は キーを 値 に マッピングする 抽象データ型 です。 [3] ハッシュテーブルは ハッシュ関数を使用して、 バケット または スロット の配列のインデックス ( ハッシュコード とも呼ばれる) を計算し 、そこから目的の値を見つけることができます。検索中にキーがハッシュされ、結果のハッシュは対応する値が格納されている場所を示します。ハッシュテーブルによって実装されたマップは ハッシュマップ と呼ばれます。
ほとんどのハッシュテーブル設計では、 不完全なハッシュ関数 が採用されています。ハッシュ関数が複数のキーに対して同じインデックスを生成する ハッシュ衝突( ハッシュ衝突)は、通常何らかの方法で対処する必要があります。ハッシュ衝突に対処するための一般的な戦略としては、リンクリストを用いて複数の要素を同じスロットに格納するチェーニングや、プローブシーケンスに従って次の利用可能なスロットを検索するオープンアドレッシングなどがあります。 [4]
適切に次元化されたハッシュテーブルでは、各検索の平均時間計算量はテーブルに格納されている要素数に依存しません。多くのハッシュテーブル設計では、 キーと値のペア の任意の挿入と削除も許可されており、 その平均コストは操作ごとに 償却定数です。 [5] [4] : 513–558 [6]
ハッシュは空間と時間のトレードオフ の一例です 。 メモリが 無限であれば、キー全体をインデックスとして直接使用し、1回のメモリアクセスでその値を検索できます。一方、処理時間が無限であれば、キーに関係なく値を保存し、 二分探索 または 線形探索 を使用して要素を取得できます。 [7] : 458
多くの場合、ハッシュテーブルは平均して 探索木 やその他の テーブル 検索構造よりも効率的であることが判明しています。ハッシュテーブルは、平均的なパフォーマンスが高速であるため、データベースのインデックス作成、キャッシュ、連想配列の実装などのタスクに、現代のソフトウェアシステムで広く使用されています。 [8] このため、ハッシュテーブルは多くの種類のコンピュータ ソフトウェア 、特に 連想配列 、 データベースのインデックス作成 、 キャッシュ 、 セット で広く使用されています。多くのプログラミング言語は、Pythonの辞書、JavaのHashMap、C++のunordered_mapなど、ハッシュの複雑さをプログラマから抽象化する組み込みのハッシュテーブル構造を提供しています。 [9]
歴史
ハッシュの概念は、それぞれ異なる場所で独立して生まれました。1953年1月、 ハンス・ピーター・ルーンは、連鎖を用いたハッシュ法を用いた IBM 社内メモを作成しました。 オープン・アドレッシング の最初の例は、 ルーンのメモを基に、AD・リンによって提案されました。 [4] : 547 ほぼ同時期に、 IBMリサーチ の ジーン・アムダール 、 エレイン・M・マグロウ 、 ナサニエル・ロチェスター 、 アーサー・サミュエルは、 IBM 701 アセンブラ にハッシュ法を実装しました 。 [10] : 124 線形プローブを用いたオープン・アドレッシングはアムダールによるものとされていますが、 アンドレイ・エルショフも 独立して同じアイデアを考案していました。 [10] : 124–125 「オープン・アドレッシング」という用語は、 W・ウェズリー・ピーターソン が大規模ファイルの検索問題を論じた論文の中で造語しました。 [11] : 15
連鎖ハッシュ法に関する最初の論文は、 素数を法とする剰余をハッシュ関数として用いるというアイデアを論じた アーノルド・デュメイによるものとされている。 [11] : 15 「ハッシュ」という言葉は、ロバート・モリスの記事で初めて発表された。 [10] : 126 線形プロービングの理論的分析は 、 コンハイムとワイスによって最初に提出された。 [11] : 15
概要
連想 配列は、キーと値のペアの 集合 を格納し、 一意のキー という制約のもとで、挿入、削除、および検索(探索)が可能です 。連想配列のハッシュテーブル実装では、 長さ の配列の一部に 要素 が格納されます( )。キー はハッシュ関数を用いてハッシュされ、 ハッシュテーブル内の インデックス位置が計算されます( ) 。ハッシュテーブルの効率は負荷係数に依存します。負荷係数は、格納されている要素数と利用可能なスロット数の比として定義され、負荷係数が低いほど一般に操作が高速になります。 [12] このインデックスには、キーとそれに関連付けられた値の両方が格納されます。キーを値と一緒に格納することで、衝突が発生した場合でも、検索時にインデックスのキーを検証して正しい値を取得できます。妥当な仮定の下では、ハッシュテーブルは、 自己平衡型二分探索木 と比較して、検索、削除、および挿入操作の 時間計算量の 境界が優れています。 [11] : 1
あ
{\displaystyle A}
メートル
{\displaystyle m}
n
{\displaystyle n}
メートル
≥
n
{\displaystyle m\geq n}
×
{\displaystyle x}
h
{\displaystyle h}
あ
[
h
(
×
)
]
{\displaystyle A[h(x)]}
h
(
×
)
<
メートル
{\displaystyle h(x)<m}
ハッシュテーブルは、各キーの格納値を省略し、キーが存在するかどうかのみを追跡することで、セットを実装するためにもよく使用されます。 [11] : 1
荷重係数
負荷 係数 はハッシュテーブルの重要な統計量であり、次のように定義される:
[
2]
α
{\displaystyle \alpha}
荷重係数
(
α
)
=
n
メートル
、
{\displaystyle {\text{荷重係数}}\ (\alpha )={\frac {n}{m}},}
n
{\displaystyle n}
ハッシュ テーブルで占有されるエントリの数です。
メートル
{\displaystyle m}
バケットの数です。
ハッシュテーブルのパフォーマンスは負荷係数に比例して低下します 。 [11] : 2 および が大きい限界では 、各バケットは統計的に ポアソン分布 を持ち、理想的にはランダムな ハッシュ関数 が期待されます 。
α
{\displaystyle \alpha}
メートル
{\displaystyle m}
n
{\displaystyle n}
λ
=
α
{\displaystyle \lambda =\alpha }
ソフトウェアは通常、負荷係数が 一定の定数 未満に維持されるようにします。これは良好なパフォーマンスの維持に役立ちます。そのため、一般的なアプローチは、負荷係数 が に達する たびにハッシュテーブルのサイズを変更、つまり「再ハッシュ」することです 。同様に、負荷係数が を下回った場合にも、テーブルのサイズが変更されることがあります 。 [13]
α
{\displaystyle \alpha}
α
最大
{\displaystyle \alpha _{\max}}
α
{\displaystyle \alpha}
α
最大
{\displaystyle \alpha _{\max}}
α
最大
/
4
{\displaystyle \alpha _{\max}/4}
個別連鎖の負荷係数
独立した連鎖ハッシュテーブルでは、バケット配列の各スロットにデータのリストまたは配列へのポインタが格納されます。 [14]
分離連鎖ハッシュテーブルは、負荷係数が増加するにつれて徐々にパフォーマンスが低下し、サイズ変更が絶対に必要となる固定ポイントはありません。 [13]
別々の連鎖では、最良のパフォーマンスが得られる値は 通常1から3の間です。 [13]
α
最大
{\displaystyle \alpha _{\max}}
オープンアドレスの負荷係数
オープンアドレス方式では、バケット配列の各スロットには正確に1つの項目が保持されます。したがって、オープンアドレス方式のハッシュテーブルでは、負荷係数は1を超えることはできません。 [14]
負荷係数が1に近づくと、オープンアドレスのパフォーマンスは非常に悪くなります。 [13]
したがって、オープンアドレスを使用するハッシュテーブルは、 負荷係数が 1に近づくと、 サイズを変更するか、 再ハッシュする 必要があります 。[13]
α
{\displaystyle \alpha}
オープンアドレス方式の場合、許容される最大負荷係数の数値は 0.6~0.75程度の範囲となる。 [15] [16] : 110
α
最大
{\displaystyle \alpha _{\max}}
ハッシュ関数
ハッシュ 関数は 、キーの集合を テーブル内のインデックスまたはスロットにマッピングします。つまり、 に対して となります。ハッシュ関数の従来の実装は 、テーブルのすべての要素が から派生するという 整数集合の仮定 に基づいています。 この場合、 の ビット長は コンピュータアーキテクチャ の ワードサイズ 内に制限されます 。 [11] : 2
h
:
あなた
→
{
0
、
。
。
。
、
メートル
−
1
}
{\displaystyle h:U\rightarrow \{0,...,m-1\}}
あなた
{\displaystyle U}
h
(
×
)
∈
{
0
、
。
。
。
、
メートル
−
1
}
{\displaystyle h(x)\in \{0,...,m-1\}}
×
∈
あなた
{\displaystyle x\in U}
あなた
=
{
0
、
。
。
。
、
あなた
−
1
}
{\displaystyle U=\{0,...,u-1\}}
あなた
{\displaystyle u}
ハッシュ関数が 与えられた集合に対して 完全 であるとは、それが に対して 単射的で ある場合 、つまり各要素が 内の異なる値にマッピングされる場合を言う 。 [17] [18] 完全なハッシュ関数は、すべてのキーが事前にわかっている場合に作成できる。 [17]
h
{\displaystyle h}
S
{\displaystyle S}
S
{\displaystyle S}
×
∈
S
{\displaystyle x\in S}
0
、
。
。
。
、
メートル
−
1
{\displaystyle {0,...,m-1}}
整数宇宙仮定
整数宇宙仮定 で使用されるハッシュ方式に は、除算によるハッシュ、乗算によるハッシュ、 ユニバーサルハッシュ 、 動的完全ハッシュ 、 静的完全ハッシュ などがあります。 [11] :2 ただし、除算によるハッシュが一般的に使用される方式です。 [19] :264 [16] :110
分割によるハッシュ
分割によるハッシュのスキームは次のとおりです: [11] : 2
ここで はハッシュ値であり 、 はテーブルのサイズです。
h
(
×
)
=
×
モッド
メートル
、
{\displaystyle h(x)\ =\ x\,{\bmod {\,}}m,}
h
(
×
)
{\displaystyle h(x)}
×
∈
S
{\displaystyle x\in S}
メートル
{\displaystyle m}
乗算によるハッシュ
乗算によるハッシュ法のスキームは以下のとおりです。 [11] : 2–3
ここで 、は非整数の 実数値定数 、 はテーブルのサイズです。乗算によるハッシュ法の利点は、 が重要ではないことです。 [11] : 2–3 任意の値で ハッシュ関数が生成されますが、 ドナルド・クヌースは 黄金比 を使用することを提案しています 。 [11] : 3
h
(
×
)
=
⌊
メートル
(
(
×
あ
)
モッド
1
)
⌋
{\displaystyle h(x)=\lfloor m{\bigl (}(xA){\bmod {1}}{\bigr )}\rfloor }
あ
{\displaystyle A}
メートル
{\displaystyle m}
メートル
{\displaystyle m}
あ
{\displaystyle A}
文字列ハッシュ
一般的に、文字列はハッシュ関数のキーとして使用されます。Stroustrup [20] は、初期値がゼロである符号なし整数を1ビットずつ左シフトし、次の文字の整数値と排他的論理和をとる単純なハッシュ関数を説明しています。このハッシュ値は、テーブルサイズを法として求められます。左シフトが循環的でない場合、文字列の長さは符号なし整数のビット数よりも少なくとも8ビット短くなります。文字列を整数にハッシュするもう1つの一般的な方法は、 多項式ローリングハッシュ関数 を使用することです。
ハッシュ関数の選択
ハッシュ値の均一分布は 、ハッシュ関数の基本要件です。不均一分布は衝突回数と衝突解決コストを増加させます。均一性は設計上保証することが困難な場合もありますが、統計的検定、例えば離散均一分布に対する ピアソンのカイ二乗検定 を用いて経験的に評価することができます。 [21] [22]
分布は、アプリケーションで発生するテーブルサイズに対してのみ均一である必要があります。特に、テーブルサイズを正確に2倍または半分にする動的なサイズ変更を使用する場合、ハッシュ関数はサイズが 2のべき乗 の場合にのみ均一である必要があります。この場合、インデックスはハッシュ関数のビット範囲として計算できます。一方、一部のハッシュアルゴリズムでは、サイズを 素数 にすることが推奨されます。 [23]
オープンアドレス 方式の場合 、ハッシュ関数は クラスタリング (2つ以上のキーを連続するスロットにマッピングすること)も回避する必要があります。このようなクラスタリングは、負荷係数が低く衝突がまれであっても、検索コストを急上昇させる可能性があります。一般的な乗法ハッシュは、特にクラスタリング挙動が悪いと言われています。 [23] [4]
K独立ハッシュ法は、 特定のハッシュ関数が特定のハッシュテーブルに対して不正なキーセットを持たないことを証明する方法を提供します。線形プロービングやカッコウハッシュ法といった衝突解決スキームにおいて、K独立性の結果は数多く知られています。K独立性はハッシュ関数が機能することを証明できるため、そのようなハッシュ関数を可能な限り高速に見つけることに集中できます。 [24]
衝突解決
ハッシュを用いた検索アルゴリズムは2つの部分から構成されます。最初の部分は、 検索キーを 配列インデックスに変換する ハッシュ関数 の計算です。理想的なケースでは、2つの検索キーが同じ配列インデックスにハッシュされることはまずありません。しかし、これは常に当てはまるとは限らず、未知のデータに対しては保証できません。 [4] : 515 したがって、アルゴリズムの2番目の部分は衝突解決です。衝突解決には、セパレートチェイニングとオープンアドレッシングという2つの一般的な方法があります。 [7] : 458
分離連鎖
ハッシュ衝突は別の連鎖によって解決される
バケット配列内のヘッドレコードとの個別の連鎖によるハッシュ衝突。
分離連鎖法では、各検索配列のインデックスに対応する キーと値のペア を持つ 連結リスト を構築する。衝突した項目は単一の連結リストを介して連結され、このリストを走査することで、一意の検索キーを持つ項目にアクセスできる。 [7] : 464 連結リストを用いた連鎖法による衝突解決は、ハッシュテーブルの実装において一般的な方法である。ハッシュテーブルを 、ノードを とする と 、操作は以下のようになる。 [19] : 258
T
{\displaystyle T}
×
{\displaystyle x}
Chained-Hash-Insert( T , k )
はリンクリスト T [ h ( k )] の先頭に x を挿入する。
連鎖ハッシュ検索( T , k )
は 、リンクリスト T [ h ( k )]内のキー k を持つ要素を検索する。
Chained-Hash-Delete( T , k ) は
リンクリスト T [ h ( k )]
から x を削除します。
要素が 数値的 または 語彙的に比較可能であり、 全体の順序 を維持してリストに挿入された場合 、失敗した検索の終了が速くなります。 [4] :520–521
個別連鎖のためのその他のデータ構造
キーが の順序付けされ ている場合、 自己バランス二分探索木 などの「 自己組織化 」概念を使用すると効率的である可能性があり、これにより 理論上の最悪ケース を まで下げることができるが 、追加の複雑さが導入される。 [4] : 521
お
(
ログ
n
)
{\displaystyle O(\log {n})}
動的完全ハッシュ法 では 、2階層のハッシュテーブルを用いて、最悪の場合でも検索の複雑さが保証されるようにする 。この手法では、エントリのバケットは、スロット を含む 完全ハッシュテーブル として編成され、 最悪の場合でも検索時間が一定となり、挿入の償却時間が短くなる。 [25] ある研究によると、高負荷環境下において、配列ベースの分離連鎖法は標準的なリンクリスト法と比較して97%も性能が向上することが分かっている。 [26] : 99
お
(
1
)
{\displaystyle O(1)}
け
{\displaystyle k}
け
2
{\displaystyle k^{2}}
各バケットに融合ツリー を使用するなどの手法 も、高い確率ですべての操作に一定の時間をもたらします。 [27]
キャッシュと参照の局所性
分離連鎖実装のリンクリストは、リンクリストのノードがメモリ上に散在している場合、 空間的局所性 ( 参照の局所性) のために キャッシュを意識 しない可能性があり、挿入および検索中のリストの走査によって CPUキャッシュの 非効率性が生じる可能性があります。 [26] : 91
キャッシュを考慮した 分離連鎖による衝突解決の変種 では、 通常はリンクリストや自己バランス型二分探索木が使用される場所で、より キャッシュフレンドリー であることが判明した 動的配列 が使用されます。これは、配列の 連続した割り当てパターンが 、ハードウェアキャッシュプリフェッチャー (例えば、 トランスレーションルックアサイドバッファ) によって利用され、アクセス時間とメモリ消費を削減できるためです。 [28] [29] [30]
オープンアドレス
ハッシュ衝突は、線形プローブを用いたオープンアドレス指定(間隔=1)によって解決されました。「Ted Baker」は固有のハッシュ値を持ちますが、それにもかかわらず「Sandra Dee」と衝突しました。「Sandra Dee」は以前に「John Smith」と衝突していました。
このグラフは、大規模なハッシュテーブル(キャッシュサイズをはるかに超える)の要素を検索するために必要なCPUキャッシュミスの平均回数を、チェイニングとリニアプローブと比較したものです。リニアプローブは 参照の局所性が 高いためパフォーマンスは向上しますが、テーブルがいっぱいになるとパフォーマンスは大幅に低下します。
オープンアドレッシング は、別の衝突解決手法であり、すべてのエントリレコードがバケット配列自体に格納され、ハッシュ解決は プロービング によって実行されます。新しいエントリを挿入する必要がある場合、バケットはハッシュ先のスロットから始まり、 プローブシーケンス に従って、空いているスロットが見つかるまで検査されます。エントリを検索する場合、バケットは同じシーケンスでスキャンされ、目的のレコードが見つかるか、未使用の配列スロットが見つかるまでスキャンされます。未使用の配列スロットが見つかると、検索は失敗となります。 [31]
よく知られているプローブ配列には以下のものがあります。
線形プロービング では、プローブ間の間隔は固定されています(通常1)。 [32]
二次プロービング では、二次多項式の連続出力を元のハッシュ計算によって与えられた値に追加することで、プローブ間の間隔が増加します。 [33] : 272
二重ハッシュ法 では、プローブ間の間隔は二次ハッシュ関数によって計算されます。 [33] : 272–273
オープンアドレッシングは、負荷係数が1に近づく とプローブシーケンスが増加するため、セパレートチェーニングに比べてパフォーマンスが低下する可能性がある。 [13] [26] : 93 負荷係数が1に達すると、テーブルが完全に埋められている場合、 プローブは 無限ループに陥る。 [7] : 471 線形プローブの平均 コストは、 クラスタリングを 避けるために要素を テーブル全体に 均一に 分散させる ハッシュ関数の能力に依存する 。クラスタが形成されると検索時間が長くなるためである。 [7] : 472
α
{\displaystyle \alpha}
キャッシュと参照の局所性
スロットは連続した場所に配置されているため、線形プローブは 参照の局所性 により CPUキャッシュの利用率を向上させ、 メモリレイテンシ を削減することができる 。 [32]
オープンアドレスに基づくその他の衝突解決技術
合体ハッシュ
合体ハッシュ は、バケットまたはノードがテーブル内でリンクする、セパレートチェイニングとオープンアドレッシングの両方を組み合わせたものです。 [34] : 6–8 このアルゴリズムは固定メモリ割り当て に最適です 。 [34] : 4 合体ハッシュにおける衝突は、ハッシュテーブル上で最大のインデックスを持つ空きスロットを特定することで解決され、衝突した値はそのスロットに挿入されます。バケットは、衝突したハッシュアドレスを含む挿入されたノードのスロットにもリンクされます。 [34] : 8
カッコウハッシュ
カッコウハッシュ法 は、オープンアドレス衝突解決手法の一種であり、 最悪のケースにおける検索複雑度と挿入処理における一定の償却時間を保証する。衝突は、それぞれ独自のハッシュ関数を持つ2つのハッシュテーブルを維持することで解決され、衝突したスロットは指定された項目に置き換えられ、そのスロットの占有されていた要素は別のハッシュテーブルに移動される。この処理は、すべてのキーがテーブルの空のバケットに独自の場所を確保するまで継続される。もしこの処理が 無限ループ に入った場合(閾値ループカウンタを維持することで識別される)、両方のハッシュテーブルは新しいハッシュ関数で再ハッシュされ、処理は継続される。 [35] : 124–125
お
(
1
)
{\displaystyle O(1)}
ホップスコッチハッシュ
ホップスコッチハッシュは、オープンアドレスベースのアルゴリズムであり、 カッコウハッシュ 、 線形プローブ 、チェイニングの要素を、バケットの 近傍 (占有されている特定のバケットの周囲の後続のバケット、いわゆる「仮想」バケット) の概念に基づいて組み合わせています。 [36] : 351–352 このアルゴリズムは、ハッシュテーブルの負荷率が90%を超えた場合に優れたパフォーマンスを発揮するように設計されています。また、 並列処理設定においても高いスループットを提供するため、サイズ変更可能な 並列ハッシュテーブル の実装に適しています 。 [36] : 350 ホップスコッチハッシュの近傍特性は、近傍内の任意のバケットから目的のアイテムを見つけるコストが、バケット自体からそのアイテムを見つけるコストに非常に近いという特性を保証します。アルゴリズムは、他のアイテムを置き換えるコストが発生する可能性はありますが、近傍にアイテムを追加しようとします。 [36] : 352
ハッシュテーブル内の各バケットには、追加の「ホップ情報」、つまり、 現在の仮想バケットに元々ハッシュされたアイテムの H − 1エントリ以内の 相対距離 を示す H ビットの ビット配列 が含まれます 。 [36] : 352 挿入されるキー と 、キーがハッシュされるバケットをそれぞれとします。挿入手順には、アルゴリズムの近傍特性が保証されるいくつかのケースが含まれます。 [36] : 352–353 が空の場合 、要素が挿入され、ビットマップの左端のビットが1に 設定され ます。空でない場合、テーブル内の空きスロットを見つけるために線形プローブが使用され、バケットのビットマップが更新されてから挿入が行われます。空きスロットが近傍の範囲内 、 つまり H − 1にない場合、各バケットの後続のスワップおよびホップ情報ビット配列操作は、その近傍 不変特性 に従って実行されます 。 [36] : 353
け
{\displaystyle k}
B
け
{\displaystyle Bk}
B
け
{\displaystyle Bk}
ロビンフッドハッシュ
ロビンフッドハッシュは、オープンアドレスに基づく衝突解決アルゴリズムです。衝突は、 その「ホームロケーション」、つまりアイテムがハッシュされたバケットから最も遠い(つまり プローブシーケンス長(PSL)が最も長い)要素を移動させることで解決されます。 [37] : 12 ロビンフッドハッシュは 理論的な検索コストを 変更しませんが、バケット上のアイテムの 分布 の 分散 に大きな影響を与えます。 [38] : 2 つまり、ハッシュテーブルにおける クラスター 形成に対処するためです。 [39] ロビンフッドハッシュを使用するハッシュテーブル内の各ノードは、追加のPSL値を格納できるように拡張する必要があります。 [40] 挿入するキーを 、 の (増分)PSL長を 、 ハッシュテーブルを 、 インデックスを とすると、挿入手順は以下のようになります。 [37] : 12–13 [41] : 5
×
{\displaystyle x}
×
。
psl
{\displaystyle x{.}{\text{psl}}}
×
{\displaystyle x}
T
{\displaystyle T}
j
{\displaystyle j}
の場合 : 反復は外部プローブを試行せずに次のバケットに進みます。
×
。
psl
≤
T
[
j
]
。
psl
{\displaystyle x{.}{\text{psl}}\ \leq \ T[j]{.}{\text{psl}}}
の場合 : アイテムを バケット に挿入します 。 と交換し ます。 を 挿入するために 番目のバケット からプローブを続行します 。 すべての要素が挿入されるまでこの手順を繰り返します。
×
。
psl
>
T
[
j
]
。
psl
{\displaystyle x{.}{\text{psl}}\ >\ T[j]{.}{\text{psl}}}
×
{\displaystyle x}
j
{\displaystyle j}
×
{\displaystyle x}
T
[
j
]
{\displaystyle T[j]}
×
′
{\displaystyle x'}
(
j
+
1
)
{\displaystyle (j+1)}
×
′
{\displaystyle x'}
動的なサイズ変更
挿入を繰り返すとハッシュテーブル内のエントリ数が増加し、結果として負荷係数が増加します。 検索および挿入操作の償却パフォーマンスを維持するために、ハッシュテーブルは動的にサイズ変更され、テーブルの項目は 新しいハッシュテーブルのバケットに 再ハッシュされます。 [13]テーブルサイズの変化は モジュロ演算 により異なるハッシュ値をもたらすため、項目をコピーすることはできません 。 [42]ハッシュテーブルがいくつかの要素を削除した後に「空になりすぎた」場合、過剰な メモリ使用を 避けるためにサイズ変更が実行されることがあります 。 [43]
お
(
1
)
{\displaystyle O(1)}
すべてのエントリを移動してサイズを変更する
一般的には、元のハッシュテーブルの2倍のサイズを持つ新しいハッシュテーブルがプライベートに 割り当て らえられ、元のハッシュテーブルのすべてのアイテムは、そのアイテムのハッシュ値を計算し、その後挿入操作を行うことで、新しく割り当てられたハッシュテーブルに移動されます。再ハッシュは単純ですが、計算コストがかかります。 [44] : 478–479
一度にすべてをやり直す代わりに
一部のハッシュ テーブル実装、特に リアルタイム システム では、ハッシュ テーブルを一度に拡大するコストを払うことができません。これは、時間的に重要な操作が中断される可能性があるためです。動的なサイズ変更を避けられない場合、解決策としては、再ハッシュ中にストレージのブリップ (通常は新しいテーブルのサイズの 50%) を回避するため、また 古いハッシュ テーブルによって発生した 大きな メモリ ブロックの割り当て解除によって ヒープ圧縮 が引き起こされる メモリの断片化を回避するために、サイズ変更を段階的に実行することです。 [45] : 2–3 このような場合、再ハッシュ操作は、ハッシュ テーブルのバケットが変更されないように、古いハッシュ テーブルに割り当てられた以前のメモリ ブロックを拡張することによって段階的に実行されます。償却再ハッシュの一般的なアプローチでは、2 つのハッシュ関数とを維持し ます 。新しいハッシュ関数に従ってバケットのアイテムを再ハッシュするプロセスは クリーニング と呼ばれ、これは 、 などの操作をカプセル化することによって コマンドパターン を通じて実装され 、バケット内の各要素が再 ハッシュ され、その手順は以下のとおりである: [45] :3
h
古い
{\displaystyle h_{\text{old}}}
h
新しい
{\displaystyle h_{\text{new}}}
あ
d
d
(
け
e
y
)
{\displaystyle \mathrm {追加} (\mathrm {キー} )}
G
e
t
(
け
e
y
)
{\displaystyle \mathrm {Get} (\mathrm {key} )}
D
e
l
e
t
e
(
け
e
y
)
{\displaystyle \mathrm {削除} (\mathrm {キー} )}
L
o
o
け
あなた
p
(
け
e
y
、
指示
)
{\displaystyle \mathrm {検索} (\mathrm {キー} ,{\text{コマンド}})}
きれいな バケツ。
T
1つの
b
l
e
[
h
古い
(
け
e
y
)
]
{\displaystyle \mathrm {表} [h_{\text{old}}(\mathrm {キー} )]}
きれいな バケツ。
T
1つの
b
l
e
[
h
新しい
(
け
e
y
)
]
{\displaystyle \mathrm {表} [h_{\text{new}}(\mathrm {キー} )]}
コマンド が 実行されます。
線形ハッシュ
線形ハッシュ はハッシュテーブルの実装であり、一度に1つのバケットごとにテーブルを動的に拡大または縮小することを可能にします。 [46]
ハッシュテーブルのパフォーマンスは、 ハッシュテーブル内のエントリに対して 準乱数 ( )を生成するハッシュ関数の能力に依存します。ここで 、 、は キー、バケットの数、 となるハッシュ関数を表します。ハッシュ関数が 異なるキーに対して 同じ値( )を生成する場合、 衝突 が発生しますが、これはさまざまな方法で対処されます。 ハッシュテーブルでの操作の一定時間計算量( )は、ハッシュ関数が衝突するインデックスを生成しないという条件を前提としています。したがって、ハッシュテーブルのパフォーマンスは、選択されたハッシュ関数の インデックス 分散 能力に 正比例します。 [47] : 1 ただし、このようなハッシュ関数の構築は 実際には実行不可能で あるため、実装では、 より高いパフォーマンスを実現するために、 ケース固有の衝突解決手法に依存しています。 [47] : 2
σ
{\displaystyle \sigma }
K
{\displaystyle K}
n
{\displaystyle n}
h
(
×
)
{\displaystyle h(x)}
σ
=
h
(
K
)
%
n
{\displaystyle \sigma \ =\ h(K)\ \%\ n}
σ
{\displaystyle \sigma }
K
1
≠
K
2
、
h
(
K
1
)
=
h
(
K
2
)
{\displaystyle K_{1}\neq K_{2},\ h(K_{1})\ =\ h(K_{2})}
お
(
1
)
{\displaystyle O(1)}
ハッシュ関数がユニバースの要素を均一に分散させ、テーブルに格納される要素がユニバースからランダムに抽出される場合、最高の性能が得られる。この場合、連鎖ハッシュ法では、探索成功の期待値は 、探索失敗の期待値は である 。 [48]
1
+
α
2
+
Θ
(
1
メートル
)
{\textstyle 1+{\frac {\alpha }{2}}+\Theta \left({\frac {1}{m}}\right)}
e
−
α
+
α
+
Θ
(
1
メートル
)
{\textstyle e^{-\alpha }+\alpha +\Theta \left({\frac {1}{m}}\right)}
アプリケーション
連想配列
ハッシュテーブルは、多くの種類のメモリ内テーブルの実装によく使用されます。また、 連想配列の 実装にも使用されます。 [33]
データベースのインデックス作成
ハッシュテーブルはディスク ベースのデータ構造や データベースインデックス( dbm など ) としても使用されるが、 これらのアプリケーションでは Bツリーがより一般的である。 [49]
キャッシュ
ハッシュテーブルは、主に低速なメディアに保存されているデータへのアクセスを高速化するための補助データテーブルである キャッシュを 実装するために使用できます。このアプリケーションでは、ハッシュの衝突は、衝突する2つのエントリのうち1つを破棄することで処理されます。通常、テーブルに現在保存されている古い項目を消去し、新しい項目で上書きすることで、テーブル内のすべての項目が一意のハッシュ値を持つようになります。 [50] [51]
セット
ハッシュテーブルは、特定の順序なしに一意の値を格納できるセットデータ構造 の実装に使用できます 。セットは通常、要素の取得ではなく、コレクション内の値のメンバーシップをテストするために使用されます。 [52]
転置表
検索された各セクションに関する情報を格納する複雑なハッシュテーブルへの 転置テーブル 。 [53]
実装
多くのプログラミング言語は、組み込みの連想配列または 標準ライブラリ モジュールとして、ハッシュ テーブル機能を提供します。
JavaScript における 「オブジェクト」とは、キーと値のペア(「プロパティ」と呼ばれる)の変更可能な集合体であり、各キーは文字列または一意性が保証された「シンボル」のいずれかです。それ以外の値は、キーとして使用される場合、まず文字列に 変換されます 。7つの「プリミティブ」データ型を除き、JavaScript におけるすべての値はオブジェクトです。 [54] ECMAScript 2015 では Map、任意の値をキーとして受け入れるデータ構造も追加されました。 [55]
C++11には 任意の型 unordered_map のキーと値を格納するための標準ライブラリ が含まれています 。 [56]
Go の組み込みでは、マップ型を 型 mapの形で実装しており 、これは多くの場合ハッシュテーブルである(ただしハッシュテーブルである保証はない)。 [57]
Java プログラミング言語には 、、、ジェネリック HashSetコレクション が HashMap含まれます 。 [58] LinkedHashSetLinkedHashMap
Python の組み込み関数は、 型 dictの形式でハッシュテーブルを実装します 。 [59]
Ruby の組み込み関数は HashRuby 2.4以降、オープンアドレスモデルを採用しています。 [60]
Rust プログラミング言語には HashMap、 HashSetRust標準ライブラリの一部としてが含まれています。 [61]
.NET 標準ライブラリには [62] と [63] が 含まれているため、 C# や VB.NET などの言語から使用することができます 。 [64] HashSetDictionary
参照
注記
^最悪のケースの 期待 時間計算量がO(log 2 (1 - α ) -1 )と なるアプローチもある (α は負荷係数)。 [1]
参考文献
^ Martin Farach-Colton、Andrew Krapivin、William Kuszmaul. 並べ替えなしのオープンアドレス指定の最適境界 . 2024 IEEE 第65回コンピュータサイエンス基礎シンポジウム (FOCS). arXiv : 2501.02305 . doi :10.1109/FOCS61266.2024.00045.
^ ab コーメン, トーマス・H. ; レイソン, チャールズ・E. ; リベスト, ロナルド・L. ; スタイン, クリフォード (2009). 『アルゴリズム入門 (第3版)』マサチューセッツ工科大学. pp. 253– 280. ISBN
978-0-262-03384-8 。
^ メルホーン, カート ; サンダース, ピーター (2008). 「ハッシュテーブルと連想配列」 (PDF) . アルゴリズムとデータ構造 . シュプリンガー. pp. 81– 98. doi :10.1007/978-3-540-77978-0_4. ISBN 978-3-540-77977-3 。
^ abcdefg ドナルド・E.・クヌース (1998年4月24日)『コンピュータプログラミングの芸術:第3巻:ソートと検索』(第2版) Addison-Wesley Professional . ISBN 978-0-201-89685-5 。
^ Leiserson, Charles E. (2005年秋). 「講義13:償却アルゴリズム、テーブル倍増、ポテンシャル法」. MIT アルゴリズム入門 6.046J/18.410J コース . 2009年8月7日時点のオリジナルよりアーカイブ。
^ Cormen, Thomas H. ; Leiserson, Charles E. ; Rivest, Ronald L. ; Stein, Clifford (2001). 「第11章 ハッシュテーブル」. アルゴリズム入門 (第2版). MIT Press and McGraw-Hill. pp. 221–252. ISBN 978-0-262-53196-2 。
^ abcde Sedgewick, Robert ; Wayne, Kevin (2011). Algorithms. Vol. 1 (4 ed.). Addison-Wesley Professional – プリンストン大学 コンピュータサイエンス学部経由.
^ Silberschatz, A.; Korth, HF; Sudarshan, S. (2020). データベースシステムの概念 (第7版). McGraw-Hill .
^ Goodrich, MT; Tamassia, R.; Goldwasser, MH (2014). 『Javaにおけるデータ構造とアルゴリズム』 (第6版). Wiley .
^ abc Konheim, Alan G. (2010). コンピュータサイエンスにおけるハッシュ . doi :10.1002/9780470630617. ISBN 978-0-470-34473-6 。
^ abcdefghijkl Mehta, Dinesh P.; Mehta, Dinesh P.; Sahni, Sartaj編 (2004). データ構造とアプリケーションハンドブック . doi :10.1201/9781420035179. ISBN 978-0-429-14701-2 。
^ タイ王国コーメン; CE、ライザーソン。 Rivest, ルイジアナ州 ;スタイン、C. (2009)。 アルゴリズム入門 (第 3 版)。 MIT を押します 。
^ abcdefg Mayers, Andrew (2008). 「CS 312: ハッシュテーブルと償却分析」. コーネル大学 コンピュータサイエンス学部. 2021年4月26日時点のオリジナルよりアーカイブ 。 2021年 10月26日 閲覧– cs.cornell.edu経由。
^ ab
James S. PlankとBrad Vander Zanden. 「CS140 講義ノート -- ハッシュ」
^ Maurer, WD; Lewis, TG (1975年3月). 「ハッシュテーブル法」. ACM Computing Surveys . 7 (1): 5– 19. doi :10.1145/356643.356645. S2CID 17874775.
^ ab Owolabi, Olumide (2003年2月). 「いくつかのハッシュ関数の実証的研究」. 情報ソフトウェア技術 . 45 (2): 109– 112. doi :10.1016/S0950-5849(02)00174-X.
^ ab Lu, Yi; Prabhakar, Balaji; Bonomi, Flavio (2006). ネットワークアプリケーションのための完全ハッシュ . 2006 IEEE 国際情報理論シンポジウム. pp. 2774– 2778. doi :10.1109/ISIT.2006.261567. ISBN 1-4244-0505-X . S2CID 1494710。
^ Belazzougui, Djamal; Botelho, Fabiano C.; Dietzfelbinger, Martin (2009). 「ハッシュ、ディスプレイス、圧縮」 (PDF) . アルゴリズム—ESA 2009: 第17回ヨーロッパシンポジウム、コペンハーゲン、デンマーク、2009年9月7~9日、議事録 . コンピュータサイエンス講義ノート . 第5757巻. ベルリン: Springer. pp. 682– 693. CiteSeerX 10.1.1.568.130 . doi :10.1007/978-3-642-04128-0_61. MR 2557794.
^ ab Cormen, Thomas H. ; Leiserson, Charles E. ; Rivest, Ronald L. ; Stein, Clifford (2001). 「第11章 ハッシュテーブル」. アルゴリズム入門 (第2版). マサチューセッツ工科大学 . ISBN 978-0-262-53196-2 。
^ Stroustrup, Bjarne (1997). 『C++プログラミング言語 第3版 』 マサチューセッツ州リーディング: Addison-Wesley. p. 503. ISBN
0-201-88954-4 。
^ ピアソン、カール (1900). 「相関変数システムの場合における、確率からの偏差の与えられたシステムが、ランダムサンプリングから生じたと合理的に想定できるという基準について」. 哲学雑誌 . シリーズ5. 50 (302): 157– 175. doi :10.1080/14786440009463897.
^ プラケット、ロビン (1983). 「カール・ピアソンとカイ2乗検定」. 国際統計評論 . 51 (1): 59– 72. doi :10.2307/1402731. JSTOR 1402731.
^ ab Wang, Thomas (1997年3月). 「Prime Double Hash Table」. 1999年9月3日時点のオリジナルよりアーカイブ 。 2015年 5月10日 閲覧。
^ Wegman, Mark N.; Carter, J. Lawrence (1981年6月). 「新しいハッシュ関数と認証および集合等価性におけるその利用」. Journal of Computer and System Sciences . 22 (3): 265– 279. doi : 10.1016/0022-0000(81)90033-7 .
^ Demaine, Erik; Lind, Jeff (2003年春). 「Lecture 2」 (PDF) . 6.897: 高度なデータ構造. MITコンピュータサイエンス・人工知能研究所 . 2010年6月15日時点のオリジナルより アーカイブ (PDF) . 2008年 6月30日 閲覧 .
^ abc Culpepper, J. Shane; Moffat, Alistair (2005). 「プレフィックス特性を制限した拡張バイトコード」. 文字列処理と情報検索 . コンピュータサイエンス講義ノート. 第3772巻. pp. 1– 12. doi :10.1007/11575832_1. ISBN 978-3-540-29740-6 。
^ Willard, Dan E. (2000). 「融合木の観点から見た計算幾何学、ファン・エムデ・ボアズ木、そしてハッシュの考察」 SIAM Journal on Computing . 29 (3): 1030– 1049. doi :10.1137/S0097539797322425. MR 1740562. 。
^ Askitis, Nikolas; Sinha, Ranjan (2010年10月). 「スケーラブルでキャッシュ効率とスペース効率に優れた文字列のトライのエンジニアリング」. VLDB Journal . 19 (5): 633– 660. doi :10.1007/s00778-010-0183-9.
^ Askitis, Nikolas; Zobel, Justin (2005年10月). 「文字列ハッシュテーブルにおけるキャッシュを考慮した衝突解決」. 第12回国際文字列処理・情報検索会議 (SPIRE 2005) の議事録 . Vol. 3772/2005. pp. 91– 102. doi :10.1007/11575832_11. ISBN 978-3-540-29740-6 。
^ Askitis, Nikolas (2009). 「整数キーのための高速かつコンパクトなハッシュテーブル」 (PDF) . 第32回オーストラレーシアコンピュータサイエンス会議 (ACSC 2009) の議事録 . 第91巻. pp. 113– 122. ISBN 978-1-920682-72-9 . 2011年2月16日時点の オリジナル (PDF)からアーカイブ 。 2010年 6月13日 閲覧。
^ テネンバウム、アーロン M.ランサム、イェディディヤ。オーゲンシュタイン、モーシェ J. (1990)。 C を使用したデータ構造 。プレンティス・ホール。 456~ 461ページ 、456ページ472.ISBN 978-0-13-199746-2 。
^ ab パグ、ラスムス ;ロドラー、フレミング・フリッシュ (2001)。 「カッコーハッシング」。 アルゴリズム — ESA 2001 。コンピューターサイエンスの講義ノート。 Vol. 2161。121 ~ 133 ページ 。CiteSeerX 10.1.1.25.4189 。 土井 :10.1007/3-540-44676-1_10。 ISBN 978-3-540-42493-2 。
^ abc コーメン、トーマス・H. ; レイソン、チャールズ・E. ; リベスト、ロナルド・L. ; スタイン、クリフォード (2001)、「11 ハッシュテーブル」、 アルゴリズム入門 (第2版)、 MITプレス および マグロウヒル 、pp. 221– 252、 ISBN 0-262-03293-7 。
^ abc Vitter, Jeffery S.; Chen, Wen-Chin (1987). 合体ハッシュ法の設計と解析 . ニューヨーク, アメリカ合衆国: Oxford University Press . ISBN 978-0-19-504182-8 – Archive.org より。
^ ラスムス・パーグ ;ロドラー、フレミング・フリッシュ (2001)。 「カッコーハッシング」。 アルゴリズム — ESA 2001 。コンピューターサイエンスの講義ノート。 Vol. 2161。121 ~ 133 ページ 。CiteSeerX 10.1.1.25.4189 。 土井 :10.1007/3-540-44676-1_10。 ISBN 978-3-540-42493-2 。
^ abcdef モーリス・ハーリヒー、ニール・シャヴィット、モラン・ツァフリル (2008). 「ホップスコッチ・ハッシュ」. 分散コンピューティング . コンピュータサイエンス講義ノート. 第5218巻. pp. 350– 364. doi :10.1007/978-3-540-87779-0_24. ISBN 978-3-540-87778-3 。
^ ab セリス、ペドロ (1986)。ロビンフッドハッシュ (PDF) 。カナダ、オンタリオ州: ウォータールー大学 、コンピューター サイエンス学部。 ISBN 978-0-315-29700-5 . OCLC 14083698. 2021年11月1日時点のオリジナルよりアーカイブ (PDF) 。 2021年 11月2日 閲覧 。
^ Poblete, PV; Viola, A. (2019年7月). 「ランダムプロービングモデルにおけるRobin Hoodおよびその他のハッシュアルゴリズムの解析(削除の有無による)」. 組合せ論、確率、計算 . 28 (4): 600– 617. doi : 10.1017/S0963548318000408 . S2CID 125374363.
^ Clarkson, Michael (2014). 「Lecture 13: Hash tables」. コーネル大学 、コンピュータサイエンス学部。2021年10月7日時点のオリジナルよりアーカイブ 。 2021年 11月1日 閲覧– cs.cornell.edu経由。
^ Gries, David (2017). 「JavaHyperTextとデータ構造:Robin Hood Hashing」 (PDF) . コーネル大学 、コンピュータサイエンス学部。 2021年4月26日時点のオリジナルよりアーカイブ (PDF) 。 2021年 11月2日 閲覧 – cs.cornell.edu経由。
^ Celis, Pedro (1988年3月28日). 外部ロビンフッドハッシュ (PDF) (技術レポート). ブルーミントン、インディアナ州: インディアナ大学 、コンピュータサイエンス学部. 246. 2021年11月3日時点のオリジナルよりアーカイブ (PDF) 。 2021年 11月2日 閲覧 。
^ Goddard, Wayne (2021). 「C5章 ハッシュテーブル」 (PDF) . クレムソン大学 . pp. 15– 16. 2023年 12月4日 閲覧 。
^ Devadas, Srini; Demaine, Erik (2011年2月25日). 「アルゴリズム入門:ハッシュテーブルのサイズ変更」 (PDF) . マサチューセッツ工科大学 、コンピュータサイエンス学部. 2021年5月7日時点のオリジナルよりアーカイブ (PDF) . 2021年 11月9日 閲覧– MIT OpenCourseWare 経由 .
^ Thareja, Reema (2014). 「ハッシュと衝突」. C言語によるデータ構造 . オックスフォード大学出版局. pp. 464– 488. ISBN 978-0-19-809930-7 。
^ ab Friedman, Scott; Krishnan, Anand; Leidefrost, Nicholas (2003年3月18日). 「組み込みシステムとリアルタイムシステムのためのハッシュテーブル」 (PDF) . All Computer Science and Engineering Research . Washington University in St. Louis . doi :10.7936/K7WD3XXV. 2021年6月9日時点のオリジナルよりアーカイブ (PDF) . 2021年 11月9日 閲覧– Northwestern University , Department of Computer Science.
^ Litwin, Witold (1980). 「線形ハッシュ:ファイルとテーブルのアドレス指定のための新しいツール」 (PDF) . Proc. 6th Conference on Very Large Databases . Carnegie Mellon University . pp. 212– 223. 2021年5月6日時点のオリジナルより アーカイブ (PDF) . 2021年 11月10日 閲覧 – cs.cmu.edu経由。
^ ab Dijk, Tom Van (2010). 「ハッシュテーブルのパフォーマンス分析と改善」 (PDF) . オランダ : トゥウェンテ大学 . 2021年11月6日時点のオリジナルより アーカイブ (PDF) . 2021年 12月31日 閲覧 。
^ Baeza-Yates, Ricardo; Poblete, Patricio V. (1999). 「第2章 探索」. Atallah (編). 『アルゴリズムと計算理論ハンドブック』 . CRC Press. pp. 2– 6. ISBN
0849326494 。
^ レフ・バナコウスキー。 「インデックスと外部ソート」。 pl:Polsko-Japońska Akademia Technik Komputerowych. 2022年3月26日のオリジナルからアーカイブ 。 2022 年 3 月 26 日 に取得 。
^ Zhong, Liang; Zheng, Xueqian; Liu, Yong; Wang, Mengting; Cao, Yang (2020年2月). 「セルラーネットワークをオーバーレイするデバイス間通信におけるキャッシュヒット率の最大化」. 中国通信 . 17 (2): 232– 238. 文献コード :2020CComm..17b.232Z. doi :10.23919/jcc.2020.02.018. S2CID 212649328.
^ Bottommley, James (2004年1月1日). 「キャッシュを理解する」. Linux Journal . 2020年12月4日時点のオリジナルよりアーカイブ。 2022年 4月16日 閲覧 。
^ Jill Seaman (2014). 「セットテーブルとハッシュテーブル」 (PDF) . テキサス州立大学 . 2022年4月1日時点のオリジナルよりアーカイブ。 2022年 3月26日 閲覧 。 {{cite web }}: CS1 maint: bot: 元のURLステータス不明( リンク )
^ “Transposition Table - Chessprogramming wiki”. chessprogramming.org . 2021年2月14日時点のオリジナルよりアーカイブ 。 2020年 5月1日 閲覧。
^ 「JavaScript のデータ型とデータ構造 - JavaScript | MDN」。developer.mozilla.org . 2022年 7月24日 閲覧 。
^ “Map - JavaScript | MDN”. developer.mozilla.org . 2023年6月20日. 2023年 7月15日 閲覧 。
^ 「プログラミング言語C++ - 技術仕様」 (PDF) . 国際標準化機構 . pp. 812– 813. 2022年1月21日時点の オリジナル (PDF)からアーカイブ。 2022年 2月8日 閲覧 。
^ 「Goプログラミング言語仕様」 go.dev . 2023年 1月1日 閲覧 。
^ 「レッスン:実装(Java™チュートリアル > コレクション)」. docs.oracle.com . 2017年1月18日時点のオリジナルよりアーカイブ 。 2018年 4月27日 閲覧。
^ Zhang, Juan; Jia, Yunwei (2020). 「機械学習に基づくRedis rehash最適化」. Journal of Physics: Conference Series . 1453 (1): 3. Bibcode :2020JPhCS1453a2048Z. doi : 10.1088/1742-6596/1453/1/012048 . S2CID 215943738.
^ Jonan Scheffler (2016年12月25日). 「Ruby 2.4 リリース:ハッシュの高速化、統合整数、丸め処理の改善」 heroku.com . 2019年7月3日時点のオリジナルよりアーカイブ。 2019年 7月3日 閲覧 。
^ “doc.rust-lang.org”. 2022年12月8日時点のオリジナルよりアーカイブ 。 2022年 12月14日 閲覧。
^ 「HashSet クラス (System.Collections.Generic)」。 learn.microsoft.com . 2023年 7月1日 閲覧 。
^ dotnet-bot. 「Dictionary クラス (System.Collections.Generic)」. learn.microsoft.com . 2024年 1月16日 閲覧 。
^ 「VB.NET HashSetの例」。Dot Net Perls 。
さらに読む
Tamassia, Roberto; Goodrich, Michael T. (2006). 「第9章 マップと辞書」. Javaにおけるデータ構造とアルゴリズム [Java 5.0対応] (第4版). ホーボーケン, ニュージャージー: Wiley. pp. 369–418. ISBN 978-0-471-73884-8 。
McKenzie, BJ; Harries, R.; Bell, T. (1990年2月). 「ハッシュアルゴリズムの選択」. ソフトウェア:実践と経験 . 20 (2): 209– 224. doi :10.1002/spe.4380200207. hdl : 10092/9691 . S2CID 12854386.
外部リンク
ウィキメディア コモンズには、ハッシュ テーブル に関連するメディアがあります 。
Wikibooksには「データ構造/ハッシュテーブル」 に関する書籍があります。
ハッシュテーブルに関する NISTエントリ
オープンデータ構造 – 第5章 – ハッシュテーブル、 Pat Morin
MITアルゴリズム入門:ハッシュ1 MIT OCW講義ビデオ
MITアルゴリズム入門:ハッシュ2 MIT OCW講義ビデオ