这是我到目前为止所做的:
struct pairhash {
public:
inline std::size_t operator()(const std::pair<int, int> &c) const
{
int x = c.first;
int y = c.second;
return ((x+y)*(x+y+1)/2 + y); // Cantor's enumeration of pairs
}
};
我需要使用这个哈希函数,这样我就可以将这对int放在这样的unordered_set中:
std::unordered_set< std::pair<int, int>, pairhash> mySet;
编辑:忘了从这对中获得坐标。更新了代码。 编辑:删除了模板代码 - 错误地添加了它。
编辑:根据SO上的另一个类似答案更改了该功能,与Cantor对的枚举相关: hash function providing unique uint from an integer coordinate pair
编辑:不要求无碰撞(感谢Petr)。
答案 0 :(得分:4)
如果您打算将其与unordered_set
(以及大多数其他容器和算法)一起使用,则不需要散列函数是无冲突的。此外,哈希表和哈希函数的一般概念是它们允许冲突,它们只是期望碰撞很少。
cppreference says about the requirements for hashing:
- 对于不相等的两个不同参数
醇>k1
和k2
,std::hash<Key>()(k1) == std::hash<Key>()(k2)
的概率应为1.0/std::numeric_limits<size_t>::max()
非常小,接近koa
。
答案 1 :(得分:2)
<强>更新强>
发布答案,发现问题已经更新。了解了我在下面的答案中提出的哈希方法的既定名称。
一般来说,如果2*sizeof(int) > sizeof(size_t)
,则不存在这样的功能。但是,假设您不会使用int
类型的整个范围,您可以尝试构建一个没有碰撞的哈希函数,以获得2个整数的足够小的值。假设a
和b
都有非负值,我可以提出以下函数:
size_t hashRangeStart(size_t n)
{
return n*(n+1)/2; // == 1 + 2 + ... + n
}
size_t intPairHash(int a, int b)
{
return hashRangeStart(a+b)+a;
}
这种方法背后的想法非常简单:
a
,b
}加起来相同的值n=a+b
会产生一系列连续的哈希值,即intPairHash(a, b) == intPairHash(a+b, 0) + a
。n
和n+1
的相邻值的哈希值范围,即intPairHash(0, a+1) == intPairHash(a, 0) + 1
。将这种方法扩展到有符号值应该不会太困难。
答案 2 :(得分:1)
散列两个整数的一种简单方法是使用Knuth的散列:
size_t hash2(int i1, int i2)
{
size_t ret = i1;
ret *= 2654435761U;
return ret ^ i2;
}