问题 int数组的c ++哈希函数


我需要专门化哈希函数 unordered_map 所以我可以使用int数组作为键。数组值通常为0或1,例如 int array = {0, 1, 0, 1},但技术上没有限制。

在这种情况下有人可以推荐一个好的哈希函数吗?或者,我总是可以将int数组转换为字符串并避免专门化。但我担心性能,因为我可能有数百万这些数组。


4780
2017-08-22 14:00


起源

使用或模仿Boost的“范围哈希”。它是通过反复呼叫建立起来的 hash_combine,这也是在Boost中,应该真的符合标准。 - Kerrek SB
如果你有几百万个这样的数组,我建议新的算法/数据结构...... - Blindy
@Blindy你会建议什么样的数据结构? - gewizz
@Kerreck,boost.org/doc/libs/1_35_0/doc/html/boost/... 说它不适合无序容器。这不适用于我的情况吗? - gewizz
@gewizz:这是草率的措辞。获取无序容器的确定性散列是不合适的 作为一个整体 [排序可能取决于负载系数和完成的重新分配数量]。然而, 当然 它适合用作 元素哈希函数 到一个无序的容器 - sehe


答案:


C ++ TR1包含一个哈希模板函数。

如果还没有,可以使用Boost Hash。

一个方便帮手的想法:

#include <boost/functional/hash.hpp>

template <typename T, int N>
    static std::size_t hasharray(const T (&arr)[N])
{
     return boost::hash_range(arr, arr+N);
}

这将(大致?)相当于

 size_t seed = 0;
 for (const T* it=arr; it!=(arr+N); ++it)
     boost::hash_combine(seed, *it);
 return seed;

如果您使用此哈希进行查找,请不要忘记实现正确的相等比较操作


6
2017-08-22 14:07



我认为应该是 std::size_t N 因为 std::size_t 保证能够表示最大可能数组的大小,同时 int 可能会溢出(取决于系统)。另外,它不需要是签名类型。 - outofthecave
@outofthecave公平点。然而,无符号是具有传染性的,这使得它对于抵消而言很笨拙(它们可能是负面的,并且 N - 10 只会缠绕 N<10。惊喜!)。此外,阵列静态输入大于2³¹的元素?那些很少见。如果你拥有它们,你通常不会对它们进行哈希处理。 - sehe


试试用 lookup8 哈希函数。这个功能非常快速而且很好。

int key[100];
int key_size=10;
for (int i=0;i<key_size;i++) key[i]=i; //fill key with sample data
ub8 hash=hash((ub8*)key, sizeof(key[0])*key_size, 0);

5
2017-08-22 18:25



那不是C ++。 - Puppy
通常哈希函数用普通c编写。您可以为它创建C ++包装器。 - vromanov
通常,写入散列函数 在手边的语言。 - Puppy
你总是编写像crc32,sha,md5这样的函数,或者使用现有的经过良好测试和高性能的实现? :) - vromanov