Unordered_map,为什么有些桶有多个元素,即使散列值都不同
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。假设哈希函数至少给出弱伪随机(即。"两两独立"或类似的)输出,当给定一个随机输入。但是,哈希函数的输出不直接用作给定输入的bin号。这将要求std::unordered_map在64位机器上具有2^64个bin…这是太多的内存。
相反,根据当前元素的数量,有一定数量的bin,例如B。map通常将哈希器的输出取B的模,以将项目映射到bin。因此,具有不同哈希值的项可以放到同一个bin中。一旦哈希表过于紧凑,根据一些启发式方法,通常会增加B,并对项目进行重新哈希以减少冲突的数量。也就是说,我们重新计算所有的哈希值然后取B'的模,而不是取更大的B'。但是它究竟如何工作是一个实现细节。
相关文章:
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 为什么映射插入和 map.find() 的单次迭代比插入和 map.find() 的两次单独迭代慢得多
- 为什么 STL 函数使用节点的颜色来计算 std::map 节点前身
- 为什么我不能在 c++ 中"map"的迭代器中使用"+1"?
- 为什么std::map有find成员函数
- 我尝试使用MAP容器来映射资源,现在RESOURCEFILE正在获取所有信息.为什么
- 为什么map有操作符[],set没有
- 为什么 memcpy() 是一种将元素添加到 'std::map' 的方法?
- 为什么我不能重载运算符<< 与 ostream 和 map( 或 unordered_map)?
- 为什么代码使用 std::map 无法编译?
- 为什么我可以将 std::map 的键传递给一个期望非常量的函数?
- 为什么 map::找不到指向 const 的指针?
- 为什么map的元素不需要复制或移动构造函数,而vector需要?
- 为什么map<string,string>接受整数作为值?
- 为什么map使用运算符[]创建新条目
- 为什么map.erase返回迭代器
- 为什么 map::operator[] 在设计上很慢
- 为什么 Map[2] 更新了错误的密钥数据?这是这样做的正确方法吗?
- 为什么map.insert()方法调用复制构造函数两次?