C# 散列整数数组

C# 散列整数数组,c#,arrays,hash,integer,C#,Arrays,Hash,Integer,我正在使用一个散列集,其中存储整数数组(32位)。这意味着我需要一个算法来散列整数数组。我正在寻找一个32位整数(C#int)散列 我尝试并编辑了两个现有的算法,您可以在底部看到的四个版本,包括它们的基准 我的问题如下: 一,。 你认为底部算法适合这个目的吗 二,。 是否有更好的算法可用于此目的 节目信息 int hash = 17; for (int i = 0, l = carCoords.Length; i < l; ++i) { hash = hash * 31 + car

我正在使用一个散列集,其中存储整数数组(32位)。这意味着我需要一个算法来散列整数数组。我正在寻找一个32位整数(C#int)散列

我尝试并编辑了两个现有的算法,您可以在底部看到的四个版本,包括它们的基准

我的问题如下:

一,。 你认为底部算法适合这个目的吗

二,。 是否有更好的算法可用于此目的

节目信息

int hash = 17;
for (int i = 0, l = carCoords.Length; i < l; ++i)
{
    hash = hash * 31 + carCoords[i].x;
    hash = hash * 31 + carCoords[i].y;
}
return hash;
  • 通常,一个数组有
    16个条目
    ,整数
    小于10,但两者都必须支持较大的值。我可以说,可能出现的最大值是200个条目和值为20的整数
  • 我在呼吸优先搜索算法中使用哈希集,比较两个节点是否相同
  • 对于这个特定的程序,我不能使用不安全的代码
基准测试和代码

下面是我的基准测试和代码,从我的程序中最差的性能到最好的性能

  • Coordinations2D是包含整数x和整数y的结构
  • 运行结束时哈希集中的总条目数为
    356525
  • 我无法准确检索碰撞的数量。给定的数字是一个对象实际被比较的次数,并且不相等(相同的散列,不同的对象)。但是,在相同的对象之间,这种情况会发生多次。由于程序是多线程的,因此每次执行该值都会有一点变化
  • 第3个种子是
    consuint seed=144
3使用直接从坐标检索的字节

代码等于 使用以下代码检索字节数组:

int size = Marshal.SizeOf(typeof(Coordinates2D));
int length = carCoords.Length;
Byte[] bytes = new Byte[size * length];
for (int i = 0; i < length; ++i)
{
    GCHandle pinStructure = GCHandle.Alloc(carCoords[i], GCHandleType.Pinned);
    Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, i*size, size);
    pinStructure.Free();
}

// Hash the byte array
return MurMurHash3.Hash(new System.IO.MemoryStream(bytes));
int size=Marshal.SizeOf(typeof(coordinance2d));
int length=carCoords.length;
字节[]字节=新字节[大小*长度];
对于(int i=0;i
这是难以置信的效率低下,因为复制

  • 性能:40880毫秒
  • 碰撞:<84
3使用从对象中的整数检索的字节

public static int Hash2(RushHourPathLengthNode.Coordinates2D[] coords)
{
    const uint c1 = 0xcc9e2d51;
    const uint c2 = 0x1b873593;

    uint h1 = seed;
    uint k1 = 0;
    uint streamLength = (uint)coords.Length * 2;

    for (int i = 0, l = coords.Length; i < l; ++i)
    {
        // Do it for X
        byte[] chunk = BitConverter.GetBytes(coords[i].x);

        /* Get four bytes from the input into an uint */
        k1 = (uint)
           (chunk[0]
          | chunk[1] << 8
          | chunk[2] << 16
          | chunk[3] << 24);

        /* bitmagic hash */
        k1 *= c1;
        k1 = rotl32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = rotl32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;


        // Do it for y
        chunk = BitConverter.GetBytes(coords[i].y);

        /* Get four bytes from the input into an uint */
        k1 = (uint)
           (chunk[0]
          | chunk[1] << 8
          | chunk[2] << 16
          | chunk[3] << 24);

        /* bitmagic hash */
        k1 *= c1;
        k1 = rotl32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = rotl32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    // finalization, magic chants to wrap it all up
    h1 ^= streamLength;
    h1 = fmix(h1);

    unchecked //ignore overflow
    {
        return (int)h1;
    }
}
public static int Hash(RushHourPathLengthNode.Coordinates2D[] coords)
{
    const uint c1 = 0xcc9e2d51;
    const uint c2 = 0x1b873593;

    uint h1 = seed;
    uint k1 = 0;
    uint streamLength = (uint)coords.Length * 2;

    for (int i = 0, l = coords.Length; i < l; ++i)
    {
        k1 = (uint)coords[i].x;

        //bitmagic hash
        k1 *= c1;
        k1 = rotl32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = rotl32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;

        k1 = (uint)coords[i].y;

        //bitmagic hash
        k1 *= c1;
        k1 = rotl32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = rotl32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    // finalization, magic chants to wrap it all up
    h1 ^= streamLength;
    h1 = fmix(h1);

    unchecked //ignore overflow
    {
        return (int)h1;
    }
}
publicstaticinthash2(RushHourPathLengthNode.coordinares2d[]coords)
{
常数c1=0xcc9e2d51;
常数c2=0x1b873593;
uint h1=种子;
uint k1=0;
uint streamLength=(uint)coords.Length*2;
for(int i=0,l=coords.Length;i|chunk[1]您是否考虑过使用空间填充曲线生成哈希?这将最小化(或消除)所选分辨率(maxX,maxY)的冲突

这里有两个使用这种方法的SO问题及其答案


  • 希望这有帮助!

    最后,我使用了上一个算法

    int hash = 17;
    for (int i = 0, l = carCoords.Length; i < l; ++i)
    {
        hash = hash * 19 + carCoords[i].x;
        hash = hash * 19 + carCoords[i].y;
    }
    return hash;
    
    int hash=17;
    对于(int i=0,l=carCoords.Length;i
    这是非常快的计算,对于(小)数字,我使用的散列非常棒


    如果要使用此选项,请确保您使用的数字是素数。因此,您无法使用位移位对其进行优化。

    我想您不想使用
    不安全的
    来处理
    int[]
    就好像它是
    字节[]
    ?对于这个特定的程序,我不能使用不安全的代码。不过,谢谢你的想法。我认为哈希代码也可以。对于CRC检查来说,这还不够好,但是对于哈希代码,你只需要一个合理的分布,这应该会给出。也可以看到这个线程:谢谢。我之前读过这个线程。布朗博士的答案类似于我在这里提供的。我不能说BlueMonkMN提供的算法有多好。也许你可以?我对你的第一个问题的回答是:这个更正很糟糕;不要使用它。作为你第二个问题的答案,我想问你一个问题:必须通过散列a来验证的确切约束是什么lgorithm?哈希表可以包含任何类型的代码(例如,您可以通过依赖简单的随机生成器创建自己的一个输出整数的代码)。或者,如果您对您提供的链接中的算法非常感兴趣,为什么不修改它,使其处理/传递整数?或者您希望我们为您这样做吗?这看起来很有希望。我将对此进行研究。我已经尝试过这一点,以及Z阶曲线。这两种方法都很好,但不适用于此问题。映射正在int上加一个on可以工作,但它仍然给我留下一个整数数组。我可以重复这个过程或做类似的事情,但最后hash3更快了。
    int hash = 17;
    for (int i = 0, l = carCoords.Length; i < l; ++i)
    {
        hash = hash * 19 + carCoords[i].x;
        hash = hash * 19 + carCoords[i].y;
    }
    return hash;