【问题标题】:How do i program a Double hash implementation meant for strings?我如何编写用于字符串的双哈希实现?
【发布时间】:2013-04-02 18:36:12
【问题描述】:

大家好,第一次来这里,但我想先问一下我对双散列的理解是否正确。

双重哈希的工作原理是首先实现一个哈希函数,然后检查该位置是否打开。如果当前点未打开,则使用第二个哈希函数确定另一个点,然后将其乘以当前尝试,然后将其添加到由第一个哈希算法确定的索引点。

我现在的代码是:

unsigned int findPos(hashedObj& x)
{
    int offset = 1;
    int iteration = 0;
    unsigned int originalPos = myhash1( x );
    unsigned int index = originalPos;
    unsigned int secondPos = myhash2( x );
    while( array[ index ].info != EMPTY && array[ index ].element != x )
    {
        iteration = offset++ * secondPos;
        if ( ( originalPos + iteration ) > array.size( ) )
            index = ( originalPos + iteration ) % array.size( );
        else
            index = originalPos + iteration;
    }
    return ( index );
}

unsigned int hash1( const string& key, const int Tsize )
{
    //start the hashvalue at 0
    unsigned int hashVal = 0;

    //cout<<" the size of the table is: "<< Tsize <<endl;

    //add the ascii value for every word to hashval, multiply by 37 each time
    for ( int i = 0; i < key.length(); i++ )
        hashVal = 37 * hashVal + key[ i ];
    //mod hashval so it remains smaller than the table size
    hashVal %= Tsize;

    //return the itemes index value
    return hashVal;
}

我刚刚意识到我没有包含我的第二个哈希函数

unsigned int hash2( const string& key, const int Tsize )
{
//store the sum of ascii numerical values
int hashVal = 0;

//add the values of all chars while multiplying each one with a prime number
for ( int i = 0; i < key.length(); i++ )
    hashVal = 29 * hashVal + key[ i ];

//mod the hashed value with a prime smaller than the table size, subtract that number
//with the prime just used and return that value
unsigned int index = 44497 - ( hashVal % 44497 );

return index;
}

它可能看起来不像,但实际上 tsize 被正确调用了。

【问题讨论】:

  • 旁注:您可能希望在计算循环中修改您的哈希值,而不是在其外部单独修改。 IE。 hashVal = (37 * hashVal + key[ i ]) % Tsize; 这可以避免可能的长字符串溢出。
  • 我在返回号码之前确实这样做了
  • 问题是,如果你使用这个函数对战争与和平进行哈希运算,你可能会在进入 mod 之前用完比特。
  • 我想我明白你们在说什么我从没想过它会发生,因为它是一个无符号整数。我正要评论我如何使用它来散列 unix 字典文件,但由于未知原因不断遇到段错误,我按照你们的建议做了,现在它消失了。我不能投票给你们因为它不会让我但是你们很棒
  • 如果您想知道为什么它只适用于我所描述的,请考虑modulo arithmetic 的链接属性。 (a*b)%c = ((a%c)*(b%c))%c。还值得注意(希望很明显)(a * (b%c))%c 同样可行。无论如何,就像我在第一条评论中向您展示的那样将它们链接起来,然后不要担心=P。

标签: c++ string-hashing double-hashing


【解决方案1】:

你的 if 语句不正确:

if ( ( originalPos + iteration ) > array.size( ) )
    index = ( originalPos + iteration ) % array.size( );
else
    index = originalPos + iteration;
}

应该是:

if ( ( originalPos + iteration ) >= array.size( ) )
    index = ( originalPos + iteration ) % array.size( );
else
    index = originalPos + iteration;
}

或者更好,因为你通过执行 if 浪费了比 % op 更多的东西,而且无论如何答案都是一样的,你可以完全摆脱 if:

index = ( originalPos + iteration ) % array.size( );

【讨论】:

  • 哦,对了,我忘了我们从 0 开始计数,而不是从 1 开始计数。
【解决方案2】:

或者你可以通过说完全简化它

unsigned int hashkey = myhash1( x );
unsigned int stepSz = myhash2( x );
while( array[ index ].info != EMPTY && array[ index ].element != x )
        hashKey = (hashKey + stepSz) % capacity;
return hashkey;

它完成了同样的事情,同时使 while 循环更小(并摆脱了额外的变量)。我假设您不想允许重复(因此 while 循环中的第二个条件?)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    • 2022-12-04
    • 2013-03-22
    • 2021-12-30
    • 2011-03-20
    相关资源
    最近更新 更多