最悪の場合でも、検索には常に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)で償却されます。
データ構造/ハッシュテーブル