C ++中无序关联容器的散列函数

时间:2013-12-07 02:22:18

标签: c++ hash unordered-map unordered-set hash-function

在C ++中,对于每个无序的关联容器(如unordered_mapunordered_setunordered_multimap),我们需要定义一个哈希函数。正如Wikipedia指出的那样,

struct X{int i,j,k;};

struct hash_X{
  size_t operator()(const X &x) const{
    return hash<int>()(x.i) ^ hash<int>()(x.j) ^ hash<int>()(x.k);
  }
};

struct hash_Xstruct X的自定义哈希函数。但是这个功能有什么用呢?为什么我们需要哈希函数?可以有任何其他类型的自定义散列函数吗?如果是这样,我们如何比较任何两个这样的功能之间的效率。

2 个答案:

答案 0 :(得分:3)

散列函数的目标是将任意数据结构的内容映射到整数,使得您可能遇到的大多数项目映射到不同的整数,并且您需要完整的项目集合'很可能会在整数集上均匀地展开。有了这样的功能,就可以很容易地构建一个能够快速查找任意项目的容器(例如unordered_map)。

我意识到这个定义有点抽象。更具体地说,请考虑上面从维基百科给出的示例。它会将结构的ijk字段进行异或,以形成哈希值。这是一个有效的散列函数(它将结构合并为一个整数)。但是,如果ijk都具有相似的值范围,那么它可能不是一个非常好的散列函数。例如,(1,2,3)(3,1,2)都将散列为相同的值。

理想的散列函数通常看起来更像是随机数生成器:对于可预测的输入,它提供看似随机的输出。 (但请记住,相同的输入必须始终提供相同的输出。)数据结构的最佳哈希函数实际上取决于您将要散列的数据类型。

这套讲义看起来涵盖了大部分要点:http://www.cs.cornell.edu/Courses/cs312/2008sp/lectures/lec21.html

您可以通过Google搜索找到其他人。

答案 1 :(得分:1)

简短回答:要快速查找元素。

与将元素存储为某种形式的red-black trees(或另一个AVL树)的有序包含相反,无序包含使用indexed buckets来包含节点。按索引检索存储区的复杂度为O(1)

Hash function是一个函数,它接受一个元素并将其转换为这样的整数索引。

因此,由于索引域小于所有元素的域,因此可能会出现collision,并且可以将更多元素放入一个桶中,从而降低元素查找的有效性。因此,碰撞的最小概率肯定是哈希函数要求的属性。另一个应该是哈希计算的有效性。

有关更多分析,请参阅Perfect Hash Function