c++使用[](int i){return i;}作为unordered_set散列函数
C++ is using [](int i){return i;} as unordered_set hash fuction good practice?
#include <iostream>
#include <unordered_set>
using namespace std;
int main()
{
auto hash = [](int i) {return i; };
unordered_set<int, decltype(hash)> s(4000, hash);
for (int i = 0; i < 4000; i++)
s.emplace(i * 4027);
cout<<s.bucket_size(0)<<endl;//4000 here ,all the keys fell into the same bucket .
return 0;
}
http://ideone.com/U1Vs1P 我发现ideone编译器使用素数4027(这是4000之后的第一个素数,4000是unordered_set的大小)作为除数来除哈希值,并使用余数来确定键应该落在哪个桶中,在这种情况下是0。
我在visual studio 2015上运行这段代码,只是将4027更改为4096,它也返回4000给我。似乎vs使用4000后2的第一次幂作为除数。
我的问题是,我有几个唯一的整数(可能是数百个),它们都在[0,4000]区间内。
我想把它们存储在哈希表中,这样我就可以快速地插入和删除这些键。
我不想浪费内存,我不想为几个int值保留一个4000长的vector
我尝试了默认的unordered_set,但是它的哈希函数太慢了。
所以我认为我可以使用[](int I){return I;}作为我的哈希函数。只要我知道我的键将以这种方式分布(我的键可能非常紧凑,如301,303,304,306,308)。
我不想浪费内存,我不想为几个int值保留一个4000长的vector
哈希表就是这样的。这是一种内存换性能的权衡。如果您想要一个可以为搜索、插入、和删除提供0(1)性能的容器,那么代价是高昂的内存成本。
基于节点的set
具有较低的内存成本,但有O(log(n))次搜索操作和大量动态分配,但插入和删除相对较快(忽略搜索时间)。基于数组的flat_set
(又名:排序的vector
)给你尽可能小的内存(以及非常快的从开始到结束迭代),但是O(log(n))的搜索和插入/删除操作对于大集合来说可能非常慢。
天下没有免费的午餐。
处理这类事情的唯一方法是确保桶的数量相对于元素的数量足够大。这将有助于减少碰撞。
如果你知道哈希表的实现和你使用的哈希函数,你可以总是构造一系列代表最坏情况的数字。但是哈希表并不是为最坏情况而优化的;它们针对一般情况进行了优化,即大多数元素不会碰撞。
也就是说,你总是可以让你的哈希函数对数字执行一些任意的数学运算。添加一个任意的固定常数,做一些位移,或者任何你觉得有效的方法。但是,这并不能阻止人们构建最坏的情况。因此,只有当你的实际代码经常发生冲突,并且你不能在不删除重要内容的情况下消除它们时,你才应该麻烦这样做。
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将Ref对象作为类成员
- 虚拟决赛作为安全
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 使用指向成员的指针将成员函数作为参数传递
- 我应该使用什么来代替void作为变体中的替代类型之一
- 何时提供默认参数作为模板参数
- 如何将 I->getType() 作为参数传递给 llvm 中的 CreateCall?
- C++使用数组作为多维数组,尽管将其初始化为带有指针的 1D
- C++匿名结构作为std::映射值
- C++:如何使函数只返回作为列表一部分的字符串
- 如何制作一个将函数作为参数的类方法
- 如何在C++中使用非静态成员函数作为回调函数
- 修改函数中的指针(将另一个指针作为参数传递)
- Clang bug?使用指针作为模板参数
- 函数作为模板参数,是否对返回类型强制约束
- 在C++中传递给函数时,为什么要指定数组大小作为参数
- 为什么 Clang 不允许"and"作为函数名称?
- 为什么 std::function 可以作为 std::not2 的参数?