我有一个名为Point的结构。点非常简单:
struct Point
{
Row row;
Column column;
// some other code for addition and subtraction of points is there too
}
Row
和Column
基本上是荣耀int
,但我厌倦了将输入参数意外地转换为函数并给它们每个包装类。
现在我使用set
点,但重复查找确实减慢了速度。我想切换到unordered_set
。
所以,我想要unordered_set
Point
。通常,该集合可能包含例如80x24终端上的每个点= 1920点。我需要一个好的哈希函数。我想出了以下内容:
struct PointHash : public std::unary_function<Point, std::size_t>
{
result_type operator()(const argument_type& val) const
{
return val.row.value() * 1000 + val.col.value();
}
};
但是,我不确定这是否真的是一个很好的哈希函数。我想要快速的东西,因为我需要很快进行很多查找。我可以使用更好的哈希函数,还是可以的?
答案 0 :(得分:19)
在 Effective Java (第2版)中给出了该技术,并在 Scala编程中引用了该技术。有一个素数常数(我们会说53但你可能会发现更大的东西会在这里给出更均匀的分布),并执行乘法和加法如下:
(53 + int_hash(row)) * 53 + int_hash(col)
对于更多值(比如添加z坐标),只需保持嵌套,如
((53 + int_hash(row)) * 53 + int_hash(col)) * 53 + int_hash(z)
其中int_hash
是散列单个整数的函数。您可以访问此页面以查找单个整数的a bunch of good hash functions。
答案 1 :(得分:2)
我认为用10比特换档比用乘以1000更有效率。
return (val.row.value()<<10) + val.col.value();
答案 2 :(得分:2)
如果域足够小,您可能会想出一个完美的哈希函数。或者也许只使用二维数组。对于较大的数据量,请使用基于素数的乘法和mod来表示您的表大小(如果您的表的大小是基数为2)。这消除了在较小的嵌入式系统上成本高昂的分频/模式。
或者找到已存在的任意数量的基于整数的散列函数。确保测量为碰撞创建的任何哈希函数。足够的碰撞将消除O(n log n)方法(例如地图/树木)的任何收益。