Unordered_map,为什么有些桶有多个元素,即使散列值都不同

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

本文关键字:为什么 map Unordered 元素      更新时间:2023-10-16

我正在玩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。假设哈希函数至少给出弱伪随机(即。"两两独立"或类似的)输出,当给定一个随机输入。但是,哈希函数的输出不直接用作给定输入的bin号。这将要求std::unordered_map在64位机器上具有2^64个bin…这是太多的内存。

相反,根据当前元素的数量,有一定数量的bin,例如B。map通常将哈希器的输出取B的模,以将项目映射到bin。因此,具有不同哈希值的项可以放到同一个bin中。一旦哈希表过于紧凑,根据一些启发式方法,通常会增加B,并对项目进行重新哈希以减少冲突的数量。也就是说,我们重新计算所有的哈希值然后取B'的模,而不是取更大的B'。但是它究竟如何工作是一个实现细节。