散列

时间:2017-07-07 07:14:23

标签: c++ hash c++14

从某些来源^,我得到一个长度为20(SHA-1)的哈希缓冲区,用于特定数据(比如文件或字节块)。如果这个给定的哈希(认为它是字符串,而不是哈希)在地图中找不到 ,那么我会提取更多信息,并使用此哈希插入此信息。说清楚:

  • unordered_map<Hash_of_20_Bytes, Information>

这是我的地图。密钥是20字节缓冲区,Information是包含详细信息的结构。所以,如果 source ^ 给了我一些哈希值,我会在这个信息图中查找该哈希并适当地使用/生成。

关键是,在我的情况下,保证给定的20字节散列没有任何冲突。但是,unordered_map仍将计算密钥的(FNV)哈希值(密钥本身是哈希值!)。我不能指示集合类而不是生成散列,而是使用密钥具有唯一键本身(以确保O(1))?

我不确定unordered_map是否也计算整数的散列(即减少额外计算的需要)。

一种方法是使用pair<20-byte, Info>本身的向量,并进行二分查找。但是,为了避免哈希计算的惩罚(通过哈希容器),它会导致更多的惩罚,使得保持向量排序)。

2 个答案:

答案 0 :(得分:4)

std::unordered_map的哈希必须满足Hash concept。所以它必须返回std::size_t,这不可能超过20个字节。

因此,不可能为这个20字节的哈希提供一个身份哈希,因此即使没有保证20字节哈希的冲突,除非它可以可靠地减少到32位空间(或者更确切地说)没有碰撞的sizeof(std::size_t)空间,对于这种情况和这个容器,碰撞是不可避免的。

答案 1 :(得分:2)

无论如何都不能使用散列,因为unordered_map期望size_t为散列,而不是20字节缓冲区。

现在,您可以做的是提供一个非常简单的自定义哈希函数:由于输入已经是一个很好的哈希,您可以将第一个sizeof(size_t)个字节并将它们粗暴地memcpy转换为{ {1}},丢弃所有其他人。我不知道你会得到令人难以置信的性能加速,但尝试这一点并不会花费太多。

  

我不能指示集合类而不是生成哈希,而是使用密钥具有唯一键本身(以确保O(1))?

这里的基本假设是有缺陷的;是的,你的密钥已经是一个好的,表现良好的哈希,所以你不需要在它上面应用复杂的哈希函数去获得预期的哈希属性你不会得到冲突键入“不同的数据映射到相同的哈希”;但一般来说,如果你有一个不错的散列函数,大多数冲突都不会来自将相同的键映射到相同散列的散列函数,而是来自散列表的当前大小 - 即来自多个散列值的事实映射到同一个存储桶。所以,再一次,你不会获得太多收益。