用C++实现哈希表冲突的避免与解决

Hash table implementation collision avoidance and resolution in C++

本文关键字:解决 冲突 C++ 实现 哈希表      更新时间:2023-10-16

我发现了这个简单的实现:

http://www.onextrabit.com/view/502c152965e7d250c5000001

然而,它没有任何共谋规避。所以我修改成这样:

#include <iostream>
#include <sstream>
using namespace std;
template <typename ElemType>
class HashTable {
private:
    // data
    ElemType* hashData;
    // hash table size
    int tableSize;
    // djb2 hash function
    int hashing(string key) {
        int hash = 5381;
        for (int i = 0; i < key.length(); i++)
            hash = ((hash << 5) + hash) + (int)key[i];
        return hash % tableSize;
    }
public:
    HashTable(int size) {
        tableSize = size;
        // init hash table data given table size
        hashData = new ElemType[tableSize];
    }
    ~HashTable() {
        delete[] hashData;
    }
    void set(string key, const ElemType& value) {
        int index = hashing(key);
        int i = 0;
        for (;(hashData[index] != (ElemType)NULL) && (i <= tableSize); i++) {
            index = (index + 1) % tableSize;
        }
        if (i > tableSize) {
            cout << "No empty bucket!" << endl;
            return ;
        }
        hashData[index] = value;
    }
    string get(string key) {
        int index = hashing(key);
        stringstream result;
        result << hashData[index];
        int i = 0;
        for (;(hashData[++index] != (ElemType)NULL) && (i <= tableSize); i++) {
            result << " or " << hashData[index];
            index %= tableSize;
        }
        return result.str();
    }
};
int main() {
    HashTable<int> hash(50);
    hash.set("Hello", 12);
    hash.set("World", 22);
    hash.set("Wofh", 25);
    for (int i = 1; i < 10; i++) {
        hash.set("Wofh", i);
    }
    cout << "Hello " << hash.get("Hello") << endl;
    cout << "World " << hash.get("World") << endl;
    cout << "Wofh " << hash.get("Wofh") << endl;
    return 0;
}

这是我第一次实现哈希表。现在,"World"answers"Wofh"从hashing()函数中得到了相同的结果。很明显,这导致了一场共谋。然而,当我想检索"世界"时,它显示了所有串通的价值观。我的问题是,有没有一种方法可以只使用线性探测来显示"世界"数字(22)?

每个表条目都需要包含一组与哈希匹配的键/值对。然后,在查找表条目后,您需要在该集合中搜索所请求的关键字。

如果碰撞很罕见,那么一个简单的成对向量可能就足够了。如果它们的频率足够高,以至于搜索太慢,并且无法通过放大表或使用更好的has函数来降低频率,那么可以考虑对向量进行排序,并使用二进制搜索,或者使用std::map或另一个哈希表(具有不同的哈希函数)来存储冲突元素。

当然,除非这是一个学习练习,否则你通常只会使用std::unordered_map(或者Boost、TR1或STL等价物,如果你不能使用C++11库的话)。

此外,在设计管理内存或其他资源的类时,请始终记住"三条规则"。如果有人试图复制你的类,你的类就会出错。