線形プロービングを使用するハッシュテーブルからエントリを削除する最良の方法は何ですか?これを行う1つの方法は、削除された要素を示すためにフラグを使用することです。これより良い方法はありますか?
簡単なテクニックは次のとおりです。
この手法により、削除が少し遅くなりますが、テーブルが整頓されます。
オーバーフローの処理方法と、(1)削除されるアイテムがオーバーフロースロットにあるかどうか、および(2)削除されるアイテム以外にオーバーフローアイテムがあるかどうか、削除されるアイテムのハッシュキーがあるかどうかによって異なります。またはおそらく他のハッシュキー。 [二重条件を見落とすことは、削除の実装におけるバグの一般的な原因です。]
衝突がリンクリストにオーバーフローした場合、それは非常に簡単です。リストをポップアップするか(空になっている可能性があります)、リンクリストの中央または最後からメンバーを削除しています。それらは楽しく、特に難しいことではありません。これをさらに効率的にするために、過剰なメモリ割り当てと解放を回避するための他の最適化があります。
線形プロービングの場合、クヌースは、スロットを空、削除、または占有としてマークする方法を用意するのが簡単なアプローチであると提案しています。削除された占有スロットを削除済みとしてマークして、線形プロービングによるオーバーフローがそれをスキップするようにしますが、挿入が必要な場合は、渡した最初の削除されたスロットを埋めることができます[The Art of Computer Programming、vol.3:Sorting and Searching 、セクション6.4ハッシュ、p。 533(ed.2)]。これは、削除がかなりまれであることを前提としています。
クヌースはアルゴリズムR6.4 [pp。 533-534]代わりに、セルを削除ではなく空としてマークし、作成したばかりの穴を別の穴の隣に移動することで、テーブルエントリを初期プローブの場所に戻す方法を見つけます。
Knuthは、これにより既存のまだ占有されているスロットエントリが移動するため、スロットへのポインタがハッシュテーブルの外側に保持されている場合はお勧めできません。 [スロットにガベージコレクションまたはその他の管理された参照がある場合、それはテーブルの外で使用されている参照であり、参照するスロットがどこにあるかは問題ではないため、スロットを移動しても問題ありません。同じオブジェクトがテーブルにあります。]
Pythonハッシュテーブルの実装(非常に高速であると言えます)は、ダミー要素を使用して削除をマークします。テーブルを拡大または縮小すると(固定サイズのテーブルを実行していないと仮定)、削除できます。同時にダミー。
コピーにアクセスできる場合は、実装に関する ビューティフルコード の記事を参照してください。
私が考えることができる最も一般的な解決策は次のとおりです。
時間が要因である場合の一般的な手法は、削除されたアイテムの2番目のテーブルを用意し、時間があるときにメインテーブルをクリーンアップすることです。一般的に検索エンジンで使用されます。
リンクリストのようなポインタを含むようにハッシュテーブルを拡張するのはどうですか?挿入時にバケットがいっぱいの場合は、このバケットから新しいフィールドが格納されているバケットへのポインタを作成します。
ハッシュテーブルから何かを削除している間、解決策は、リンクリストからノードを削除する関数を作成する方法と同等になります。