1

ハッシュ テーブルを編集してダブル ハッシュ クラスを作成しようとしていますが、うまくいきません。

誰かが洞察力を持っているかどうか疑問に思っていました。新しい戦略を使用して新しいプローブを提供する必要がある findPos() を編集するだけでよいと言われました。

**いくつかの調査を行ったところ、二重プローブでは R-(x mod R) を使用すると言われています。ここで R >size と素数はテーブル サイズよりも小さくなります。では、新しい再ハッシュ関数を作成しますか?

ここに私のコードがあります:

template <typename HashedObj>
class HashTable
{
  public:
    explicit HashTable( int size = 101 ) : array( nextPrime( size ) )
      { makeEmpty( ); }

    bool contains( const HashedObj & x ) const
    {
        return isActive( findPos( x ) );
    }

    void makeEmpty( )
    {
        currentSize = 0;
        for( auto & entry : array )
            entry.info = EMPTY;
    }

    bool insert( const HashedObj & x )
    {
            // Insert x as active
        int currentPos = findPos( x );
        if( isActive( currentPos ) )
            return false;

        if( array[ currentPos ].info != DELETED )
            ++currentSize;

        array[ currentPos ].element = x;
        array[ currentPos ].info = ACTIVE;
            // Rehash; 
        if( currentSize > array.size( ) / 2 )
            rehash( );
        return true;
    }

    bool insert( HashedObj && x )
    {
            // Insert x as active
        int currentPos = findPos( x );
        if( isActive( currentPos ) )
            return false;

        if( array[ currentPos ].info != DELETED )
            ++currentSize;

        array[ currentPos ] = std::move( x );
        array[ currentPos ].info = ACTIVE;

            // Rehash; see Section 5.5
        if( currentSize > array.size( ) / 2 )
            rehash( );

        return true;
    }

    bool remove( const HashedObj & x )
    {
        int currentPos = findPos( x );
        if( !isActive( currentPos ) )
            return false;

        array[ currentPos ].info = DELETED;
        return true;
    }

    enum EntryType { ACTIVE, EMPTY, DELETED };

  private:
    struct HashEntry
    {
        HashedObj element;
        EntryType info;

        HashEntry( const HashedObj & e = HashedObj{ }, EntryType i = EMPTY )
          : element{ e }, info{ i } { }

        HashEntry( HashedObj && e, EntryType i = EMPTY )
          : element{ std::move( e ) }, info{ i } { }
    };

    vector<HashEntry> array;
    int currentSize;

    bool isActive( int currentPos ) const
      { return array[ currentPos ].info == ACTIVE; }

    int findPos( const HashedObj & x ) const
    {
        int offset = 1;
        int currentPos = myhash( x );

        while( array[ currentPos ].info != EMPTY &&
               array[ currentPos ].element != x )
        {
            currentPos += offset;  // Compute ith probe
            offset += 2;
            if( currentPos >= array.size( ) )
                currentPos -= array.size( );
        }

        return currentPos;
    }

    void rehash( )
    {
        vector<HashEntry> oldArray = array;

            // Create new double-sized, empty table
        array.resize( nextPrime( 2 * oldArray.size( ) ) );
        for( auto & entry : array )
            entry.info = EMPTY;

            // Copy table over
        currentSize = 0;
        for( auto & entry : oldArray )
            if( entry.info == ACTIVE )
                insert( std::move( entry.element ) );
    }

    size_t myhash( const HashedObj & x ) const
    {
        static hash<HashedObj> hf;
        return hf( x ) % array.size( );
    }
};
4

2 に答える 2

0

私はあなたのコードを理解しているかどうか確信が持てませんが、答えとして考えるべきではないいくつかの観察をさせてください。

  1. 二次プロービングを使用する場合、メソッドでは としていくつかfindPos()進める必要があると思います。現在、私が見ているように、あなたは1単位で増加します(最初は1です)、2単位の後、4単位などです。currentPoscurrentPos*currentPos % array.size()currentPosoffset
  2. おそらく、二次プローブを計算するための高速な方法を試しています。この場合、offset2 倍するのではなく、2 倍する必要があります。それはいくつかのようoffset *= 2になりますが、衝突の数をカウントする必要があるため、増加させる必要がありoffsetます。
  3. たぶん、より簡単な方法は次のとおりです。

    currentPos += 2*offset++ - 1; // fast way of doing quadratic resolution

テーブルが少なくとも半分空になることが保証され、その結果、挿入が実行されたときに availables エントリの検索が保証される場合、サイズ変更は問題ありません。

幸運を

于 2015-10-17T20:25:02.233 に答える