2d索引的良好哈希函数

时间:2010-04-14 03:25:30

标签: c++ hash

我有一个名为Point的结构。点非常简单:

struct Point
{
    Row row;
    Column column;

    // some other code for addition and subtraction of points is there too
}

RowColumn基本上是荣耀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();
    }
};

但是,我不确定这是否真的是一个很好的哈希函数。我想要快速的东西,因为我需要很快进行很多查找。我可以使用更好的哈希函数,还是可以的?

3 个答案:

答案 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)方法(例如地图/树木)的任何收益。