散列技术,使用unordered_map

时间:2016-04-21 05:26:58

标签: c++ hash unordered-map

所以我的教授刚刚分配了this家庭作业。我知道我对哈希技术的分享,但是我完全不知道如何不因冲突而失去很多分数,因为1百万字符串会在我的哈希表中暴力冲突。

我应该关注什么?

  1. 创建一个非常好的重新哈希技术,以检测何时发生冲突并适当地重新哈希
  2. 专注于如何将字符串转换为唯一的整数,以避免使用某种基于素数的模数进行碰撞。
  3. 或许我只是完全误解了作业。你们怎么去解决这个问题呢?任何想法都会非常有用。

2 个答案:

答案 0 :(得分:1)

您的老师要求您散列100万个字符串,并且您有2 ^ 32 = 4,294,967,296个不同的32位整数值。

使用20个字符的随机字符串,大量可能的字符串比哈希值更多,因此不能将特定字符串映射到特定哈希值,以限制碰撞潜力(也就是说你有< = 2 ^ 32个潜在的字符串,因为字符串长度较短,或者每个字符被允许采取的值受到限制 - 你有机会获得完美的哈希函数:一个公式映射每个一个已知的不同数字)。

因此,您基本上不得不尝试随机但可重复从字符串映射到哈希值。随之而来的是“生日悖论”,这意味着你必须期待相当多的碰撞。多少?好吧 - this answer提供了公式 - 对于 m 存储桶(2 ^ 32)和 n 插入(1,000,000):

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

换句话说,对于随机字符串输入,平均最好的哈希函数将会有116次冲突。

你的老师说:

  

最终得分为最高{0,200-5 * T}

所以,完成这项任务是没有意义的:你更有可能在前花园里拥有一块24克拉的金色流星土,而不是获得正分。

也就是说,如果你想为这个类实现最少的冲突次数,那么低性能(不是特别是缓存友好)但最小的冲突选项就是拥有一组随机数据......

uint32_t data[20][256] = { ... };

从互联网网站下载一些真正随机的数据以填充它。丢弃任何重复的数字(在C ++中,您可以使用std:set<>来查找它们)。逐个字符位置(0..19)然后是字符值,通过对值进行异或来生成散列。

碰撞图示

如果不相信上述信息,您可以生成一百万个随机32位值 - 就好像它们是不同字符串的哈希值 - 并查看哈希值重复的频率。任何给定的运行应该产生的输出与上面计算的116碰撞平均值相差不远。

#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)

答案 1 :(得分:1)

任务是创建零冲突的哈希函数。 TonyD刚刚将预期的碰撞计算为116.根据评分,对于116次碰撞的散列函数,你将获得零点。

教授提示使用unordered_map,这对设计哈希函数没有帮助。这可能是一个棘手的问题......

您如何设计一个为100万输入返回可重复的唯一数字的函数?