如何在2D平面中散列几何点?

时间:2012-06-07 16:27:10

标签: java algorithm hash

简单地说,我有很多(x,y)形式的点。

我想把这些点放入一个哈希表中,点是键。

我应该如何实现类hashCode()的{​​{1}}方法?以Java为语言

Point

3 个答案:

答案 0 :(得分:2)

数字往往聚集在大多数坐标平面上;因为,我们倾向于使用舒适范围内的数字。出于这个原因,不可取的是微不足道的xor组合,因为x == y将碰撞的所有数字,以及x + 1 == y等所有数字都会发生冲突。

为避免这种情况,我建议您在使用x坐标进行x坐标之前反转y坐标的字节。这将组合一个输入的大多数可变性(低位字节)的区域与另一个输入的最小可变性区域(高位字节)。在考虑数字簇时(例如x的值在1和1000之间),这样的算法将给出更均匀的分布。

由于哈希算法在散列产生数字字段而没有大量聚类时效果最好,因此这种解决方案实际上会使哈希相关的数据结构更快,因为哈希冲突的频率较低。

以下是当然没有优化的,你可以根据自己的需要修改它,但这是基本的想法:

public int hashCode() {

    long bits = Double.doubleToLongBits(y);
    byte[] ybits = new byte[] {
        (byte)((y >> 56) & 0xff),
        (byte)((y >> 48) & 0xff),
        (byte)((y >> 40) & 0xff),
        (byte)((y >> 32) & 0xff),
        (byte)((y >> 24) & 0xff),
        (byte)((y >> 16) & 0xff),
        (byte)((y >> 8) & 0xff),
        (byte)((y >> 0) & 0xff),
    };
    byte[] xbits = new byte[] {
        (byte)((x >> 56) & 0xff),
        (byte)((x >> 48) & 0xff),
        (byte)((x >> 40) & 0xff),
        (byte)((x >> 32) & 0xff),
        (byte)((x >> 24) & 0xff),
        (byte)((x >> 16) & 0xff),
        (byte)((x >> 8) & 0xff),
        (byte)((x >> 0) & 0xff),
    };
    // this combines the bytes of X with the reversed order
    // bytes of Y, and then packs both of those into 4 bytes
    // because we need to return an int (4 bytes).
    byte[] xorbits = new byte[] {
         (xbits[0]^ybits[7])^(xbits[4]^ybits[3]),
         (xbits[1]^ybits[6])^(xbits[5]^ybits[2]),
         (xbits[2]^ybits[5])^(xbits[6]^ybits[1]),
         (xbits[3]^ybits[4])^(xbits[7]^ybits[0]),
    };

    int value = 0;
    for (int i = 0; i < 3; i++) {
       value = (value << 8) + (by[i] & 0xff);
    }
    return value;
}

我建议的初始优化是将哈希码缓存在对象中以供后续查找,如果分析表明它是一个问题,也许更有效地管理创建/销毁的数组。

答案 1 :(得分:0)

我不确定双人的哈希有多好,但你应该能够做到:

public int hashCode() {
  return x.hashCode() ^ y.hashCode();
}

如果这在测试中产生了太多的冲突(你这样做了吗?),你可以通过位移,幻数等来改变它。所有类型的按位运算,确实。

这是Java吗?我的答案基于我对C#的经验。

答案 2 :(得分:0)

您可以使用您想要的任何功能。这一切都取决于您的坐标是什么样的典型值,以及您希望哈希函数有多好。

如果是你所有的点都在1到1百万的范围内,那么你可以使用这样的东西(这是C ++代码,不知道你使用的是哪种语言)。

size_t hashCode = (size_t)x * (size_t)y;

或者您可以添加值,或乘以值,或做任何您想做的事。

size_t hashCode = (size_t)(x+y);

size_t hashCode = (size_t)(x*y);

甚至

size_t hashCode = (size_t)(x*y) + (size_t)(x+y);