1. ホーム
  2. c++

[解決済み] C++でリニアプロービングを実装するには?

2022-02-02 10:33:10

質問内容

Hash Mapsを初めて使うのですが、明日が課題の提出日です。私はすべてを実装し、衝突が発生したときを除いて、すべてうまくいきました。リニアプロービングの考え方がよく理解できません。理解したことに基づいて実装してみましたが、テーブルサイズ < 157の場合、プログラムがなぜか動かなくなりました。

void hashEntry(string key, string value, entry HashTable[], int p) 
    {
        key_de = key;
        val_en = value;
       for (int i = 0; i < sizeof(HashTable); i++)
        {
        HashTable[Hash(key, p) + i].key_de = value;
        }
    }

ハッシュ関数に毎回数字を追加することで、2つのバケットが同じHashインデックスになることはないと考えました。しかし、それはうまくいきませんでした。

どのように解決するのですか?

線形プローブによるハッシュテーブルでは、以下のことが必要です。

  1. ハッシュ化された場所から、キーと値を格納するための空のスロットの線形探索を開始する。
  2. 見つかったスロットが空であれば、キー+値を格納して終了です。
  3. そうでない場合は、キーが一致したら値を置き換えて完了です。
  4. そうでない場合は、次のスロットに移動して、空のスロットやキーが一致するスロットを探します。その時点で、(2) または (3) が実行されます。
  5. オーバーランを防ぐため、これらすべてを行うループは、テーブルサイズに応じてラップされる。
  6. もし、ハッシュ化された元の場所まで戻っても、空のスロットやマッチングキーの上書きがない場合、テーブルは完全に埋まり(100%の負荷)、それ以上キーと値のペアを挿入することができなくなります。

以上です。実際にはこのような感じです。

bool hashEntry(string key, string value, entry HashTable[], int p)
{
    bool inserted = false;
    int hval = Hash(key, p);

    for (int i = 0; !inserted && i < p; i++)
    {
        if (HashTable[(hval + i) % p].key_de.empty())
        {
            HashTable[(hval + i) % p].key_de = key;
        }

        if (HashTable[(hval + i) % p].key_de == key)
        {
            HashTable[(hval + i) % p].val_en = value;
            inserted = true;
        }
    }

    return inserted;
}

線形プロービングハッシュアルゴリズムでテーブルを拡張するのは面倒なので注意しましょう。それは皆さんの勉強の中で、これから出てくるのではないでしょうか。最終的には、テーブルが特定の負荷率(例えば80%)を超えたら、テーブルを拡張し、すべてのエントリを新しい p のサイズにすると、最終的な置き場所が変わってしまいます。

とにかく、ご理解いただけたでしょうか。