在C ++中,对于每个无序的关联容器(如unordered_map
,unordered_set
,unordered_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_X
是struct X
的自定义哈希函数。但是这个功能有什么用呢?为什么我们需要哈希函数?可以有任何其他类型的自定义散列函数吗?如果是这样,我们如何比较任何两个这样的功能之间的效率。
答案 0 :(得分:3)
散列函数的目标是将任意数据结构的内容映射到整数,使得您可能遇到的大多数项目映射到不同的整数,并且您需要完整的项目集合'很可能会在整数集上均匀地展开。有了这样的功能,就可以很容易地构建一个能够快速查找任意项目的容器(例如unordered_map
)。
我意识到这个定义有点抽象。更具体地说,请考虑上面从维基百科给出的示例。它会将结构的i
,j
和k
字段进行异或,以形成哈希值。这是一个有效的散列函数(它将结构合并为一个整数)。但是,如果i
,j
和k
都具有相似的值范围,那么它可能不是一个非常好的散列函数。例如,(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