ハッシュテーブル操作O(1)とはどのようなデータですか?


18

答えから(いつ)ハッシュテーブルルックアップはO(1)ですか?、データが特定の統計条件を満たしている場合、ハッシュテーブルには少なくとも償却されたO(1)最悪の場合の振る舞いがあり、これらの条件を広くするのに役立つテクニックがあります。

しかし、プログラマーの観点から、私は自分のデータが何であるかを事前に知りません。それはしばしば外部ソースから来ます。そして、一度にすべてのデータを取得することはめったにありません。挿入と削除は、ルックアップの速度をそれほど下回らない速度で行われることが多いため、データを前処理してハッシュ関数を微調整します。

だから、一歩を踏み出す:データソースに関する知識があれば、ハッシュテーブルにO(1)操作の可能性があるかどうか、そしておそらくハッシュ関数で使用するテクニックを判断するにはどうすればよいですか?


ああ、ハッシュテーブルとバイナリツリーは関連していますが、ここではハッシュテーブルと、それらが最高の状態(またはそうでない状態)に焦点を当てています。
ジル「SO-停止されて悪」

ハッシュ関数の最良のケースは、データが均一に分布している場合です。
0x0

@Sunil:違います。カスタマイズされたハッシュ関数を使用できます。
ラファエル

この質問は広すぎると思います。特に、データソースに関する知識がどのようになるかを具体的に説明できますか?
ラファエル

@Raphaelたとえば、キーが文字列の場合:人の名前、ディレクトリ内のファイル名、XMLタグ、ファイルハッシュ、…
Gilles 'SO- stop being evil'

回答:


4

最悪の場合でも、検索には常にO(1)操作が必要であることを保証するいくつかの手法があります。

ハッシュテーブルにO(1)操作がある可能性があるかどうか、またおそらくハッシュ関数で使用するテクニックを判断するにはどうすればよいですか?

最悪のケースは、悪意のある攻撃者(Mallory)が、Malloryがシステムの実行を遅くするために特別に選択したデータを意図的に提供した場合に発生します。

特定のハッシュ関数を選択した後、マロリーが選択したハッシュ関数を見つけられないと仮定するのはおそらく楽観的すぎるでしょう。Malloryが選択したハッシュ関数を検出すると、Malloryがそのハッシュ関数を使用して多くのデータをハッシュテーブルに挿入できるようにすると、運命づけられます:Malloryは、数十億のデータ項目を内部的に迅速に生成し、ハッシュ関数を使用して、衝突する可能性のあるデータ項目を見つけてから、衝突する可能性がある数百万のデータ項目をフィードします。これにより、O(1)よりもはるかに遅いルックアップが実行されます。

「最悪の場合でもO(1)ルックアップ」を保証するすべてのテクニックは、各挿入で少し余分な作業を行うことでこの問題を回避し、将来、可能なすべてのルックアップがO(1)時間で成功することを保証します。 。特に、(最悪の場合)マロリーは遅かれ早かれ、使用しているハッシュ関数を発見すると仮定します。ただし、別のハッシュ関数(集計ハッシュまたはその他のユニバーサルハッシュ)を選択する前に、いくつかのデータアイテムを挿入する機会があるのは、これまでに取得したすべてのデータを2で検索できるように特別に選択したものですまたは3つのプローブ-すなわち、O(1)。この関数をランダムに選択するため、Malloryはしばらくの間どの関数を選択したかを知らないことをかなり確信で​​きます。たとえマロリーであってもこの新しいハッシュ関数でも以前のデータと衝突するデータをすぐに提供します。その後、新しいハッシュ関数をさらに選択して、リハッシュした後、彼と他の人が私たちに与えたすべての以前のデータを見ることができます最悪の場合は2つか3つのプローブでアップします。つまり、最悪の場合はO(1)ルックアップです。

新しいハッシュ関数をランダムに選択し、各ルックアップが常にO(1)であることを保証するのに十分な頻度でテーブル全体を再ハッシュするのはかなり簡単です。これにより、各ルックアップが常にO(1)になることが保証されますが、これらの手法は、N-1個のアイテムを既にN-1個のアイテムを含むハッシュテーブルに挿入する場合、その挿入にO(N)時間を必要とする場合があります。ただし、新しいハッシュ関数を使用して以前のデータと衝突する新しいデータをマロリーが故意に提供する場合でも、システムはマロリーなどからの多くのアイテムを受け入れる前に受け入れることができるようにシステムを設計することができます完全なO(N)再構築。最悪の場合でも、O(1)ルックアップを保証するために、新しい関数と再ハッシュを選択するハッシュテーブル手法には、次のものがあります。

  • カッコウハッシュは、各キー検索が最大2つのハッシュ計算と2つのテーブル検索で成功することを保証します。
  • ホップスコッチハッシュは、テーブル内の連続したエントリを少数のH(おそらくH = 32)で検査した後、各キールックアップが成功することを保証します。
  • ダイナミックパーフェクトハッシュ -Dietzfelbingerによる1994年の論文は、各キールックアップが常に2つのハッシュ計算と2つのルックアップで成功することを保証するために「頻繁に」再ハッシュしますが、それを指摘した最初の記事です完全な再ハッシュを行うことはめったにないため、各完全な再ハッシュでO(n)時間を使用しても、挿入と削除の予想平均コストはO(1)で償却されます。

データ構造/ハッシュテーブル



5

O(1)

O(1)O(n2W)

O(logn/loglogn)O(1)


5

私はデータ構造の専門家ではありませんが、ハッシュの通常の理論的アプローチは、関数のファミリー(たとえば、)を定義してから、ランダムに選択されたファミリーのメンバーに対する最悪のケースの入力。敵事前にランダムな選択知らない。これは、ランダム化されたアルゴリズムの分析方法にも似ています。入力分布ではなく、アルゴリズムの選択が期待されます。ha,b(x)=ax+bmodp

過去には、CrosbyとWallachによるUsenixの論文によると、一般的なプログラミング言語はこのようなことを行わず、多くのWebアプリ(および他のサーバー)が製造上の衝突に基づくDoS攻撃にさらされていました。(この論文は2003年のものですが、ダンバーンスタインがかなり以前に同じアイデアを発見したことを示唆しています。)

クイックグーグル検索は、実装に関する最新技術が改善されている改善されいないという主張を提供します。

別の余地は、高帯域幅の世界では、タイミング攻撃により、オンラインで衝突を見つけるのがそれほど難しくないことです(Crosby-Wallachリンクが示唆するように、オフラインではありません)。ダニエルゴロビンは、数年前にタイミング攻撃に対して脆弱ではないデータ構造で結果を出したことを覚えているようですが、それらが広く使用されているかどうかはわかりません。


0

ハッシュテーブルの平均ケース分析は、入力の均一性という通常の仮定の下で行われます。これは、かつてoccamのかみそりのために行われます。

ドメインとキーの分布に関する追加の知識がある場合は、少なくとも理論的には、同じ平均ケース分析を行い、均一な分布を分布に置き換えて、予想を再計算できます。

もちろん、この難しさは、不均一なアベレージケース分析が実行しにくいという事実に起因しています。そして、あなたの「知識」は、そのような分析で簡単に使用できる分布として便利に表現できないかもしれません。

明らかに、最も簡単なことはシミュレーションです。ハッシュテーブルを実装し、通常の入力セットに対してそれらがどのように機能するかを観察します。


8
私は最初の文に反対しなければなりません。標準的な仮定は、ハッシュ関数が入力データではなくランダムであることです。データが均一に分散していると仮定すると、分析は空想の領域に押し込まれます。実際のデータは決して均一ではありません。しかし、ハッシュ関数を十分に均一にするための教科書のテクニックがあります。ユニバーサルハッシュ、特に集計ハッシュを参照してください。
-JeffE

@JeffE Raphaelの回答の平均ケース分析を見て、彼はこの均一性の仮定を述べています。分布なしで平均ケース分析を行うことはできません。1つを選択する必要があり、nonが指定されている場合、occamのカミソリは均一なものを提案します。
ウリ

6
もちろん、ディストリビューションがあります。ハッシュ関数を選択するために使用する分布です。入力データの配布を選択することは、街灯の下で紛失したキーを探すようなものです。確かに、光は良いですが、おそらくあなたがそれらを落とした場所ではありません。
-JeffE

@JeffEこれは、平均ケース分析が行われ、分布を選択して計算を開始する方法です。いつものように、ディストリビューションの選択は議論の余地があります。不均一な平均​​ケース分析を行うことは大歓迎です。
ウリ

4
はい、できあがりです。(プロファイルを確認してください。)分析を予測(分析の全体のポイント)にしたい場合は、ハッシュ関数をランダム化する必要があります。次に、正確な分布を選択します。
-JeffE

-1

有限の既知のセットの特定のケースとしての(固定長の)順列:このペーパーのように、一意の番号を順列に割り当てるのは比較的簡単です。長さ順列をサイズ配列にマッピングするために、これを(やや気味の悪い実装で)使用しました。しかし、最終的にすべての順列が必要になるため、これを行うことができました。サブセットのみを使用している場合、そのサブセットに合わせた関数または効率的なスパース配列が必要になります。nn!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.