无序多集的hash/crc算法
Algorithm for hash/crc of unordered multiset
假设我想创建一个无序的无符号int的无序多集集。为此,我需要创建一个哈希函数来计算无序多集的哈希。事实上,这对CRC也有好处。
一个显而易见的解决方案是将项目放在向量中,对它们进行排序,并返回结果的散列。这似乎有效,但价格昂贵。
另一种方法是对值进行异或,但很明显,如果我有一个项目两次或没有,结果会是一样的——这是不好的。
我有什么想法可以更便宜地实现这一点吗?我有一个应用程序,它将为数千台和相对较大的设备提供数千台。
由于它是一个多集,您希望相同多集的哈希值相同,这些多集的表示可能具有以不同顺序呈现、添加或删除的相同元素。然后,您希望散列值是可交换的,易于更新,并且可以随元素的每次更改而更改。您还希望两个更改不会轻易取消它们对哈希的影响。
除最后一个条件外,满足所有条件的一个操作是加法。只需对元素求和即可。要使和保持有界,请对哈希值的大小进行模和运算。(例如,64位散列的模264。)要确保插入或删除零值会更改散列,请先在每个值上加一。
总和的一个缺点是两个变化很容易抵消。例如,将1 3替换为2 2。为了解决这个问题,您可以使用相同的方法,对条目的多项式求和,仍然保持交换性。例如,您可以对x2+x+1求和,而不是对x+1进行求和。现在,用相同的总和来设计一组变化变得更加困难了。
这里有一个合理的std::unordered_multiset<int>
哈希函数,如果计算是在大素数的基础上进行的话会更好,但这个想法仍然有效。
#include <iostream>
#include <unordered_set>
namespace std {
template<>
struct hash<unordered_multiset<int>> {
typedef unordered_multiset<int> argument_type;
typedef std::size_t result_type;
const result_type BASE = static_cast<result_type>(0xA67);
result_type log_pow(result_type ex) const {
result_type res = 1;
result_type base = BASE;
while (ex > 0) {
if (ex % 2) {
res = res * base;
}
base *= base;
ex /= 2;
}
return res;
}
result_type operator()(argument_type const & val) const {
result_type h = 0;
for (const int& el : val) {
h += log_pow(el);
}
return h;
}
};
};
int main() {
std::unordered_set<std::unordered_multiset<int>> mySet;
std::unordered_multiset<int> set1{1,2,3,4};
std::unordered_multiset<int> set2{1,1,2,2,3,3,4,4};
std::cout << "Hash 1: " << std::hash<std::unordered_multiset<int>>()(set1)
<< std::endl;
std::cout << "Hash 2: " << std::hash<std::unordered_multiset<int>>()(set2)
<< std::endl;
return 0;
}
输出:
Hash 1: 2290886192
Hash 2: 286805088
当它是素数p时,碰撞次数与1/p成正比。我不确定二次幂的分析是什么。您可以通过在插入/删除整数x时添加/减去BASE^x来高效更新哈希。
将内部multiset实现为值->count哈希映射。
这将使您能够通过以下方式避免偶数元素通过xor抵消的问题:您不用对每个元素进行xor运算,而是根据计数和值构造一个新的数字(例如,将它们相乘),然后可以使用xor构建完整的哈希。
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- 当比特数不是8的倍数时,使用切片8算法计算CRC
- 无序多集的hash/crc算法
- 加快文件扫描的CRC算法