unordered_map,为什么有的桶不止1个元素,哈希值也不一样?

unordered_map, why some buckets have more than 1 element even hashed values are all different?

我正在使用 std::unordered_map 的默认哈希函数并检查是否发生了冲突。下面是代码:

void check(std::map<long, bool> & mp, const string & s, const long v){
    if(mp.count(v) == 0){
        mp[v] = true;
    }else{
        cout<<"collision for "<<s<<endl;
    }
}
int main(){
    std::unordered_map<std::string, long> um;
    std::map<long, bool> map;
    auto hasher = um.hash_function();

    std::string str = "";

long count = 0;

    for (int i = 0; i < 26; ++i)
    {
        str = char(65+i);
        um[str];
        auto value = hasher(str);
        check(map, str, value);

        for (int j = 0; j < 26; ++j)
        {
            str = char(65+i);
            str += char(65+j);
            um[str];
            auto value = hasher(str);
            check(map, str, value);

            for (int k = 0; k < 26; ++k)
            {
                str = char(65+i);
                str += char(65+j);
                str += char(65+k);
                um[str];
                auto value = hasher(str);
                check(map, str, value);

                for (int l = 0; l < 26; ++l)
                {
                    str = char(65+i);
                    str += char(65+j);
                    str += char(65+k);
                    str += char(65+l);
                    um[str];
                    auto value = hasher(str);
                    check(map, str, value);

                    for (int m = 0; m < 26; ++m)
                    {
                        str = char(65+i);
                        str += char(65+j);
                        str += char(65+k);
                        str += char(65+l);
                        str += char(65+m);
                        um[str];
                        auto value = hasher(str);
                        check(map, str, value);
                    }
                }
            }
        }
    }
        for(int i = 0; i < um.bucket_count(); ++i){
        if(um.bucket_size(i) >= 2)cout<<"um_collison happened at "<<i<<"  "<<um.bucket_size(i)<<endl;
    }

    return 0;
}

我遇到的问题是,我发现 collision for 没有输出,但是有很多像 um_collison happened at 17961055 3 这样的输出,我正在使用 g++ 4.9.2,为什么字符串被散列为不同的值,但一些桶仍然有超过 1 个元素?

哈希函数返回的值是一个size_t。假定哈希函数在给定随机输入时至少给出弱伪随机(即 "pairwise independent" 或类似)输出。但是,散列函数的输出并不直接用作给定输入的 bin 编号。这将需要 std::unordered_map 在 64 位机器上有 2^64 个 bins...这太多内存了。

取而代之的是,根据当前的元素数量,有一定数量的箱子,比如 B。映射通常采用散列器的输出,对 B 取模,以将项目映射到箱子。因此,具有不同哈希值的项目可以进入同一个容器。一旦散列 table 变得太紧,根据一些启发式算法,通常 B 会增加并且项目将重新散列以减少冲突次数。也就是说,我们重新计算所有哈希值,然后取模 B' 而不是更大的 B'。但它究竟如何工作是一个实现细节。