删除C ++时的hashkey碰撞

时间:2009-10-15 01:50:16

标签: c++

为了使搜索foreach“符号”我想从我的hashTable中删除,我选择生成我插入的哈希键。但是,我在删除函数中看到的问题是当我需要从发现碰撞的地方删除符号时,它先前导致我的while循环条件测试false我不想要的地方。

bool hashmap::get(char const * const symbol, stock& s) const
{
    int hash = this->hashStr( symbol );
    while ( hashTable[hash].m_symbol != NULL )
    {       // try to find a match for the stock associated with the symbol.
        if ( strcmp( hashTable[hash].m_symbol , symbol ) == 0 )
        {
            s = &hashTable[hash];
            return true;
        }
        ++hash %= maxSize;
    }
    return false;
}

bool hashmap::put(const stock& s, int& usedIndex, int& hashIndex, int& symbolHash)
{
    hashIndex = this->hashStr( s.m_symbol ); // Get remainder, Insert at that index.
    symbolHash = (int&)s.m_symbol;
    usedIndex = hashIndex;

    while ( hashTable[hashIndex].m_symbol != NULL ) // collision found
    {
        ++usedIndex %= maxSize; // if necessary wrap index around
        if ( hashTable[usedIndex].m_symbol == NULL )
        {
            hashTable[usedIndex] = s;
            return true;
        }
        else if ( strcmp( hashTable[usedIndex].m_symbol , s.m_symbol ) == 0 )
        {
            return false; // prevent duplicate entry
        }
    }
    hashTable[hashIndex] = s; // insert if no collision 
    return true;
}
// What if I need to remove an index i generate?
bool hashmap::remove(char const * const symbol)
{
    int hashVal = this->hashStr( symbol );
    while ( hashTable[hashVal].m_symbol != NULL )
    {
        if ( strcmp( hashTable[hashVal].m_symbol, symbol ) == 0 )
        {
            stock temp = hashTable[hashVal]; // we cansave it
            hashTable[hashVal].m_symbol = NULL;
            return true;
        }
        ++hashVal %= maxSize; // wrap around if needed 
    }        // go to the next cell meaning their was a previous collision
    return false;
}

int hashmap::hashStr(char const * const str)
{   
    size_t length = strlen( str );
    int hash = 0;
    for ( unsigned i = 0; i < length; i++ )
    {
        hash = 31 * hash + str[i];
    }
    return hash % maxSize;
}

从先前的碰撞中删除hashTable中的“符号”我需要做什么? 我希望它不是直接在上面的java方程式。

2 个答案:

答案 0 :(得分:3)

看起来你正在实现一个带有开放寻址的哈希表,是吗?删除在该计划中有点棘手。见http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

“打开寻址时删除键是有问题的:如果有两个碰撞键x和y,其中h(x)= h(y),并且键x在键y之前插入,并且想要删除键x,这不能简单地通过将T [h(x)]标记为FREE来完成,因为那时将不再找到y。一种可能性是将T [h(x)]标记为DELETED(另一个特殊条目),这是跳过的当搜索密钥时,标记为DELETED的表格地点也可以重新用于存储想要插入的另一个密钥z,如果确定该密钥z已经不在表中(即,到达结束时)密钥z的探测序列并没有找到它。这种重复使用使插入方法变得复杂。而且,带有DELETED键的地方填满了表格。“

答案 1 :(得分:1)

您需要做的是创建一个表示“已删除”项目的虚拟标记值。在表中插入新值时,需要检查元素是否为NULL或“已删除”。如果插槽包含此sentinel“已删除”值或插槽为NULL,则插槽是插入的有效插槽。

也就是说,如果您要编写此代码用于生产,则应考虑使用boost::unordered_map,而不是滚动自己的哈希映射实现。如果这是为了学业,那么,祝你好运。