我正在寻找最佳的方式来计算一个哈希码的一组bi-维点(因此,我可以存放面hashtable).

有一些明显的方式做到这一点,诸如串联的所有各点的坐标在一串及其哈希码,但这将非常缓慢。

在另一端的速碰撞频谱,我还可以例如总结了所有的坐标,这将导致一个非常快速的代码,而且也将创造一个很大的冲突。

什么是最佳的方式来计算一个哈希码的一套点?

是最佳解决方案不同,如果这些坐标的整数(vs真实的坐标)?

编辑:我使用。净所以哈希码应该是32位长。

有帮助吗?

解决方案

有对这份工作没有最佳方式。这一切都取决于你有多大的散列能负担得起。你必须做的速度和扩散之间tradoffs。请记住,有没有这样的东西作为最佳的解决方案(如果你并不确切地知道你要什么散列)在某些情况下异能足够好了。

就拿此代码

unsigned int JSHash(char* str, unsigned int len)
{
    unsigned int hash = 1315423911;
    unsigned int i    = 0;

    for(i = 0; i < len; str++, i++)
    {
        hash ^= ((hash << 5) + (*str) + (hash >> 2));
    }

    return hash;
}
/* End Of JS Hash Function */

您说agregating点一起是减缓。如果修复上代码它不需要任何形式的agregation的只是通过trought(没有太大的不同,总结),如果你使用的是integeres和浮你可能会修复移位(<<和>>是移位操作,它们一起工作就像按位旋转)以适合的数据类型。

检查这里其他散列函数: http://www.partow.net/programming/hashfunctions/

其他提示

优化依赖于从散列运算您的要求。

性能会在更散列冲突的成本。

你有硬约束的一方?这将归结为是如何散列冲突的多少,每百分数要花费你在性能方面的数学分析。

如果您的数据集是通过任何机会,可以有共同的边缘,但不重叠,否则,您只需要在三个点散列每个多边形以避免碰撞多边形之一。

编辑:重提此,描绘可能的碰撞与凹/凸边界,它是一样好你的多边形重叠。 -

唉:当凸和凹相遇,它总是让我陷入困境。 :-P

可替换地,可以只XOR各个点的散列。

return p1.GetHashCode() ^ p2.GetHashCode()

根据什么值将是反正。也许只需要添加他们。

如果你想要面定义的顺时针逆时针方向,但在其他方平等的,是平等的,然后你就必须创造一种规范功能。一个函数,给多边形分开始从任何时候和在任何顺序将返回点在平等的顺序。

一种算法,我所能想的就是找到最低的所有可能的序列要点:

  1. 找到设定的最左边点(分配的最低x点与最低y),这些都是起始点。
  2. 每个起点,每个方向,迭代地增加连接点的指定方向并消除所有这不是顶级的-左边在目前的迭代。停止当只有一个起始点,方向对是左或当n-1迭代完成的。如果超过一个起点和方向是剩余的,选择的任何-他们都是同构的。
  3. 重新排序的分开始从中发现点在于找到方向。

这是O(n^2)最糟糕的情况下对完全退化面,但是如果你的面没有重叠点,这是O(n),一个漂亮的小恒的因素。

与该规范化以便可以容易地比较两个面对平等的,只是反复进行比较分平等。哈希码的计算,也是微不足道的,使用的任何合理稳健的散列结合的方法。例如:

int result = 0;
foreach (var point in this.points) {
    result = (result * 31 + point.X.GetHashCode()) * 31 + point.Y.GetHashCode();
}

有关与顺时针/逆时针独立性所需性能的非常快(计算),散列你不希望依赖于找到一个明确的点的顺序。

这限制了你的散列组合操作来者,其通勤。因此,我们希望保持组合操作过程中的任何和所有数据,其独立取向分开的。

下面是一个简单的解决方案:

假设一个结合函数int - > INT - > INT是缔合 以下任何会做开始:

public static int combine(int h, int x)
{
    return h * 31 + x;
} 

public static int combine(int h, int x)
{
    return h ^ x;
} 

然后,我们可以执行以下操作:

public override int GetHashCode()
{
    int x = 0;
    int y = 0;
    uint h = 0;    
    foreach (var point p in polgon)
    {
        x = combine(x, p.X);
        y = combine(y, p.Y);
        h++;
    }
    // simplified, unrolled Murmur2 hash for end stage
    const uint m = 0x5bd1e995;
    const int r = 24;
    uint h = count;
    uint k = ReinterpretInt32ToUInt32(x);
    k *= m;
    k ^= k >> r;
    k *= m;
    h *= m;
    h ^= k;
    k = ReinterpretInt32ToUInt32(y);
    k *= m;
    k ^= k >> r;
    k *= m;
    h *= m;
    h ^= k;
    // avalanche
    h ^= h >> 13;
    h *= m;
    h ^= h >> 15;
    return ReinterpretUInt32ToInt32(h);
}

靠着这使上面的代码容易

public unsafe uint ReinterpretInt32ToUInt32(int i)
{
    return *((uint*) (void*) &i);
}

public unsafe int ReinterpretUInt32ToInt32(uint u)
{
    return *((int*) (void*) &u);
}

这不会在防撞方面最好的哈希,但应该是非常快的计算,你可能会发现它足以满足您的需求。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top