C++:为unordered_set编写一个自定义哈希函数,该函数使用哈希表中的桶数
C++ : Writing a custom hash function for unordered_set that uses the number of buckets in the hash table
我正在为类Coord(二维坐标)编写一个自定义哈希函数。
是否可以更改下面的哈希函数,使b是Undered_set哈希表中当前的bucket数量,并且如果bucket数量发生更改,则会更改?
namespace std
{
template <>
struct hash<Coord>
{
size_t operator()(const Coord &k) const
{
int b = 11;
int a1 = static_cast<int> (pow(b,(1.0/3.0)));
int a2 = static_cast<int> (pow(b,(2.0/3.0)));
return ((a1*k.getX() + a2*k.getY()) % b);
}
};
}
唯一可移植且有效的方法是计算在std::size_t范围内尽可能均匀分布的哈希。对于给定的密钥,散列函数在程序的持续时间内返回相同的散列代码是很重要的。
随着无序映射的增长,它将重新散列自己。由于密钥是不可变的,因此不可能将新的bucket计数传递给密钥以计算新的散列(在任何情况下,散列都将在映射中进行模运算)。
更进一步:
试图将bucket计数传递给键(例如,通过引用或可变数据成员)只会以撕裂告终,这将是一个错误。
一个问题是,这会将这个键类与map类耦合——这已经够糟糕的了,但是。。。
更糟糕的是,无序映射不会与您通信,以警告您它将要重新散列。你必须在插入项目后发现这一点。这意味着地图中的所有项目现在都有基于旧bucket计数的哈希。尝试在映射中插入重复项很可能会起作用,破坏映射的语义!
要做到这一点,每次插入后,你必须将所有项目删除到一个向量中,重新计算它们的哈希值,然后重新插入它们。
恐怖!!!
请告诉我,我已经说服你不要走这条末日之路。
我认为这不是一个好主意,因为如果哈希表增长,所有的哈希都会改变,影响现有元素。只需返回a1*k.getX() + a2*k.getY()
,哈希表实现将为您完成必要的模部分。
也就是说,你可以通过std::unordered_map::bucket_count()
获得桶的数量,并将其存储在你的哈希对象中(只是为了说明,不要这样做):
struct MyHash {
std::size_t bucket_count;
size_t operator()(const Coord &k) const {
int a1 = static_cast<int> (pow(b,(1.0/3.0)));
int a2 = static_cast<int> (pow(b,(2.0/3.0)));
return ((a1*k.getX() + a2*k.getY()) % bucket_count);
}
};
相关文章:
- 如何为位集找到/实现一个好的哈希函数
- 对于短字符串来说,这是一个很好的哈希函数吗?
- 我在C++中使用提升哈希函数将 3 个双精度组合成一个面临冲突的哈希
- 无冲突的哈希函数
- 在 C++ 中为特定哈希表创建插入函数
- Qt5 哈希函数在 Windows 7 和 Windows10 上不会返回相同的哈希
- 解决由于在哈希函数中使用了不完整的类型而导致的编译失败
- 使用 Murmur2 64 位哈希函数生成会导致冲突的输入
- 错误:哈希函数必须可使用键类型的参数进行调用
- unordered_set是否适合存储矢量<int>元素的数据结构?如果是这样,我将如何实现哈希函数?
- 为什么C++哈希函数的返回类型是 std::size_t,而不是独立于平台的类型?
- 哈希函数计算
- 哈希函数中同一键的不同值和良好的哈希值排序
- 将 C# 哈希函数转换为C++
- 如何创建用于生成噪声的哈希函数
- 插入不从哈希函数中检索键
- 哈希<T>,更少的<T>函数:模板参数后的空括号
- 替代搜索函数和哈希向量<struct>C++
- 哈希表添加函数
- 完美的函数哈希函数生成器