C++ 使用无序映射的散列技术
所以我的教授刚刚布置了家庭作业。我知道我在散列技术中所占的份额,但我完全不知道如何避免由于冲突而丢失很多分数,因为一百万个字符串会在我的散列表中强行执行冲突 我应该关注什么C++ 使用无序映射的散列技术,c++,hash,unordered-map,C++,Hash,Unordered Map,所以我的教授刚刚布置了家庭作业。我知道我在散列技术中所占的份额,但我完全不知道如何避免由于冲突而丢失很多分数,因为一百万个字符串会在我的散列表中强行执行冲突 我应该关注什么 创建一个非常好的重新散列技术来检测何时发生冲突并适当地重新散列 重点介绍如何将字符串转换为唯一整数,以避免使用某种基于素数的模发生冲突 或者我只是完全误解了任务。你们怎么解决这个问题。任何想法都会非常有用。你的老师让你散列100万个字符串,你有2^32=4294967296个不同的32位整数值可用 对于20个字符的随机字符串
或者我只是完全误解了任务。你们怎么解决这个问题。任何想法都会非常有用。你的老师让你散列100万个字符串,你有2^32=4294967296个不同的32位整数值可用
对于20个字符的随机字符串,可能的字符串比散列值多得多,因此无法以限制冲突可能性的方式将特定字符串映射到特定散列值(例如,假设您有任务是创建一个具有零冲突的hashfunction。TonyD刚刚计算出预期冲突为116。根据评分,您将获得具有116次冲突的hashfunction的零分 教授给出了一个使用
unordered\u map
的提示,这对设计hashfunction没有帮助。这可能是一个技巧性的问题
你将如何设计一个函数,为100万个输入返回一个可重复的唯一数字?我根本不认为要求你提供哈希表……只是哈希函数本身……无论如何,对于具体问题,我会问助教。作业没有提到,但教授说如果我们使用
无序映射将更容易de>。是否可以编辑unordered_map
用于解决此问题的散列函数?@SamPerales是(阅读一些文档)但是散列函数必须为同一参数返回相同的散列。冲突检测是其他人的工作。@SamPerales:赋值中没有任何东西需要unordered\u map
,但是如果您想在提交之前使用自己的一组随机字符串测试散列函数,请使用std::unordered\u map num\u value;
将允许您计算散列到给定值的字符串值的数量:for(auto&s:strings)++num_冲突[hash(s)]
。num_values
上的循环可以查找值>=2,表示冲突。也就是说,如果将哈希函数插入到无序映射中,并且存储了字符串,那么也会出现大量冲突,表示哈希函数的质量,但将32位哈希空间包装到较小的存储桶索引空间(默认的max\u load\u factor
为1.0,您可以预期>=1000000但<~2000000个存储桶)。不幸的是,我不知道unit32_t数据类型,但你帮了我很大的忙。我将按照你的回答,尝试实现数组方法。还有什么我应该尝试让我的生活更轻松的吗?uint32_t
是C++11的可选部分-请参见。在大多数硬件上,它与unsigned int
相同,因此,如果
标题缺少它,只需typedef unsigned uint32\u t
或使用unsigned
(int
是隐式的)。我不知道你怎么能想象任何高质量的哈希算法会比从数组查找中XOR一些数据更容易…我从来没有见过这么简单的事情。哦,我明白了,谢谢。我感觉我走的方向是正确的。我只有一个问题,数组查找是特定于数组的,还是其他更快的线性数据结构s干扰算法?@SamPerales:“其他更快的线性数据结构会干扰算法吗?”-没有比数组更快索引查找的数据结构,因此你的问题没有意义。我想不出任何聪明的方法。我唯一能求助的方法是,允许116次冲突,然后返回,以某种方式使用第二个不同的散列为它们腾出空间function@MarkusKull:“这可能是个骗人的问题……”-如果以哈希为主题,这将是非常反常的,并且没有什么教育价值,但是谁知道呢。。。。
expected collisions = n - m * (1 - ((m-1)/m)^n)
= 1,000,000 - 2^32 * (1 - ((2^32 - 1) / 2^32) ^ 1,000,000)
= 1,000,000 - 2^32 * (1 - 0.99976719645926983712557804052625)
~= 1,000,000 - 999883.6
~= 116.4
uint32_t data[20][256] = { ... };
#include <iostream>
#include <map>
#include <random>
int main()
{
std::random_device rd;
std::map<unsigned, int> count;
for (int i = 0; i < 1000000; ++i)
++count[rd()];
std::map<int, int> histogram;
for (auto& c : count)
++histogram[c.second];
for (auto& h : histogram)
std::cout << h.second << " hash values generated by " << h.first << " key(s)\n";
}
$ ./poc
999752 hash values generated by 1 key(s)
124 hash values generated by 2 key(s)
$ ./poc
999776 hash values generated by 1 key(s)
112 hash values generated by 2 key(s)
$ ./poc
999796 hash values generated by 1 key(s)
102 hash values generated by 2 key(s)
$ ./poc
999776 hash values generated by 1 key(s)
112 hash values generated by 2 key(s)
$ ./poc
999784 hash values generated by 1 key(s)
108 hash values generated by 2 key(s)
$ ./poc
999744 hash values generated by 1 key(s)
128 hash values generated by 2 key(s)