列表上的哈希函数独立于其中的项目顺序

时间:2011-11-18 20:45:51

标签: c# algorithm hash-function

我想要一个字典,为一组整数赋值。

例如key[1 2 3]value具有一定的价值。

问题是[3 2 1]在我的情况下需要被视为相同,所以如果我使用哈希方法,哈希需要相等。

该套装将有2到10个项目。

项目总和通常是固定的,因此我们不能根据总和制作哈希码,这是第一个自然的想法。

不是家庭作业,实际上在我的代码中遇到了这个问题。

这个集合在C#中基本上是IEnumerable<int>所以任何数据结构都可以存储它们。

任何帮助表示赞赏。性能在这里也非常重要。

立即想到:我们可以总结一下items^2并且已经获得了一些更好的哈希值,但我仍然希望听到一些想法。

编辑:真的很抱歉,大家都建议订购,我没想到我需要说实际订购和散列是目前的解决方案我使用,我正在考虑更快的替代方案。

9 个答案:

答案 0 :(得分:4)

基本上,这里的所有方法都是同一模板的实例化。将x 1 ,...,x n 映射到f(x 1 )op ... op f(x n ) ,其中op是某些集合X上的可交换关联操作,f是从项目到X的映射。此模板已被使用了几次,证明是好的。

  • 在[1,p - 1]中选择随机大素数p和随机残基b。设f(x)= b x mod p,并将op加法。我们基本上将一个集合解释为多项式,并使用Schwartz–Zippel lemma来约束碰撞的概率(=非零多项式将b作为根mod p的概率)。

  • 让op为XOR,让f为随机选择的表。这是Zobrist hashing,通过简单的线性代数参数最小化了预期的冲突次数。

模幂运算很慢,所以不要使用它。至于Zobrist散列,有300万个项目,表格f可能不适合L2,尽管它确实设置了一个主存储器访问的上限。

我会把Zobrist散列作为一个出发点,并寻找一个行为类似于随机函数的廉价函数f。这本质上是非加密伪随机生成器的工作描述 - 我会尝试通过用x播种快速PRG并生成一个值来计算f。

编辑:假设集合都具有相同的总和,不要选择f为1次多项式(例如,线性同余生成器的阶梯函数)。

答案 1 :(得分:2)

使用HashSet<T>HashSet<T>.CreateSetComparer(),返回IEqualityComparer<HashSet<T>>

答案 2 :(得分:1)

我认为本文中提到的内容肯定会有所帮助:

http://people.csail.mit.edu/devadas/pubs/mhashes.pdf

增量多集散列函数及其在内存完整性检查中的应用

摘要:我们引入了一种新的加密工具:多重集散列函数。与将字符串作为输入的标准散列函数不同,多集散列函数在多集(或集)上运行。它们将任意有限大小的多重集合映射到固定长度的字符串(散列)。它们是渐进的,当新成员被添加到多集中时,散列可以在时间上与更改成比例地更新。这些函数可能是多重冲突抵抗的,因为它很难找到产生相同散列的两个多重集,或者只是设置冲突抵抗,因为它很难找到一个产生相同散列的集合和多集合。

答案 3 :(得分:1)

我认为你的平方思想正朝着正确的方向发展,但功能选择不佳。我会尝试更像PRNG函数或者只是乘以一个大素数,然后是所有结果值的XOR。

答案 4 :(得分:0)

一种可能性:对列表中的项进行排序,然后将其哈希。

答案 5 :(得分:0)

您可以对数字进行排序并从预定的索引中选择一个样本,如果当前值的数字较少,则将其余值保留为零。或者你可以把它们或其他任何东西弄清楚。

答案 6 :(得分:0)

为什么不喜欢

public int GetOrderIndependantHashCode(IEnumerable<int> source)
{
    return (source.Select(x => x*x).Sum()
            + source.Select(x => x*x*x).Sum()
            + source.Select(x => x*x*x*x).Sum()) & 0x7FFFFF;
}

答案 7 :(得分:0)

如果key中的值的范围恰好限于低位正整数,则可以使用简单查找将每个值映射到素数,然后将它们相乘以得到{{{ 1}}。

使用问题中的示例:

value

答案 8 :(得分:-1)

创建自己的实现IEnumerable<T>的类型。

覆盖GetHashCode。在其中,对您的收藏品进行排序,调用并返回ToArray().GetHashCode()