boost::hash_combine
1.boost::hash_combine的作用
boost::hash_combine是 Boost 库中用于组合多个哈希值的辅助函数。它通常用于自定义类型(struct/class)的哈希函数,用于像std::unordered_map或std::unordered_set这样的哈希容器。
如果有一个结构体包含多个成员,想根据这些成员生成一个哈希值,单纯地对每个成员哈希再简单相加可能冲突多,hash_combine提供了一种较好的组合方式。
2.boost::hash_combine的实现原理
在 Boost 1.55 中,它大致定义如下:
template<classT>inlinevoidhash_combine(std::size_t&seed,constT&v){std::hash<T>hasher;seed^=hasher(v)+0x9e3779b9+(seed<<6)+(seed>>2);}解释:
seed是之前已有的哈希值,可以是初始值0。v是当前需要组合进哈希的值。0x9e3779b9是黄金比例常数(232/ϕ2^{32}/\phi232/ϕ),用于增加哈希的均匀性。(seed<<6) + (seed>>2)是为了混合之前的哈希值,减少冲突。^=将新值与已有的seed结合起来。
这种组合方式被证明对小型结构体哈希效果不错。
3. 基本使用方法
假设我们有一个自定义类型Point:
#include<boost/functional/hash.hpp>#include<unordered_set>#include<iostream>structPoint{intx,y;booloperator==(constPoint&other)const{returnx==other.x&&y==other.y;}};// 自定义哈希函数structPointHash{std::size_toperator()(constPoint&p)const{std::size_t seed=0;boost::hash_combine(seed,p.x);boost::hash_combine(seed,p.y);returnseed;}};intmain(){std::unordered_set<Point,PointHash>s;s.insert({1,2});s.insert({3,4});for(constauto&p:s)std::cout<<"("<<p.x<<","<<p.y<<")\n";}说明:
- 先定义一个
seed(初始为0)。 - 对每个成员调用
boost::hash_combine(seed, value)。 - 最终返回
seed作为整体的哈希值。
4. 组合多个成员的示例
假设结构体更复杂:
structPerson{std::string name;intage;doubleheight;};structPersonHash{std::size_toperator()(constPerson&p)const{std::size_t seed=0;boost::hash_combine(seed,p.name);boost::hash_combine(seed,p.age);boost::hash_combine(seed,p.height);returnseed;}};boost::hash_combine可以处理任何支持std::hash的类型。- 可以无限次组合多个成员。
5. 注意事项
boost::hash_combine并不会保证完全无冲突,只是降低冲突概率。- 对浮点数组合时,注意可能的精度问题。
- 对自定义类成员递归组合即可。
6. 总结
boost::hash_combine(seed, value)是组合哈希值的标准方法。- 常用于自定义类型哈希函数。
- 使用模式:
size_t seed=0;hash_combine(seed,member1);hash_combine(seed,member2);hash_combine(seed,member3);returnseed;boost::hash_range
1. 概述
boost::hash_range是 Boost 库中boost::functional::hash模块提供的一个函数模板,用于对一段区间(range)中的元素生成哈希值。它常用于需要对容器内容进行哈希的场景,比如将std::vector、std::list等放入unordered_map或unordered_set时。
#include<boost/functional/hash.hpp>2. 函数原型
namespaceboost{template<classInputIt>std::size_thash_range(InputIt first,InputIt last);}模板参数
InputIt:输入迭代器类型,通常为容器的迭代器。参数
first:区间起始迭代器(包含)last:区间结束迭代器(不包含)
返回值
返回std::size_t类型的哈希值。
特点:
- 支持任意类型的容器,只要元素类型可哈希(可以被
boost::hash<T>支持)。 - 哈希结果会考虑元素顺序,所以
{1,2,3}和{3,2,1}的哈希值不同。 - 可用于自定义容器作为键的哈希函数。
3. 内部原理
hash_range的核心思路是对区间内的每个元素进行哈希,并通过一个迭代式的合并算法得到最终哈希值,类似下面的伪代码:
std::size_t seed=0;for(autoit=first;it!=last;++it){seed^=boost::hash_value(*it)+0x9e3779b9+(seed<<6)+(seed>>2);}returnseed;其中:
0x9e3779b9是黄金分割常数,用于减少冲突。seed << 6和seed >> 2是位混合操作。- 每个元素的哈希值会与前一个累积的
seed混合,从而生成一个整体哈希。
4. 使用示例
示例 1:对std::vector<int>生成哈希
#include<iostream>#include<vector>#include<boost/functional/hash.hpp>intmain(){std::vector<int>v={1,2,3,4,5};std::size_t h=boost::hash_range(v.begin(),v.end());std::cout<<"Hash of vector: "<<h<<std::endl;return0;}输出类似:
Hash of vector: 1234567890示例 2:在unordered_map中使用容器作为 key
#include<iostream>#include<vector>#include<unordered_map>#include<boost/functional/hash.hpp>structVectorHash{std::size_toperator()(conststd::vector<int>&v)const{returnboost::hash_range(v.begin(),v.end());}};intmain(){std::unordered_map<std::vector<int>,std::string,VectorHash>map;map[{1,2,3}]="Hello";map[{4,5,6}]="World";std::vector<int>key={1,2,3};std::cout<<"Value: "<<map[key]<<std::endl;// 输出 Helloreturn0;}解释:
- 自定义
VectorHash作为哈希函数。 boost::hash_range将整个 vector 的内容转换为单一哈希值。
示例 3:哈希自定义结构体内的区间
#include<vector>#include<boost/functional/hash.hpp>structMyStruct{std::vector<int>data;booloperator==(constMyStruct&other)const{returndata==other.data;}};structMyStructHash{std::size_toperator()(constMyStruct&s)const{returnboost::hash_range(s.data.begin(),s.data.end());}};- 可与
std::unordered_set<MyStruct, MyStructHash>搭配使用。 - 注意:要同时实现
operator==。
5. 注意事项
顺序敏感
hash_range会考虑元素顺序,因此{1,2,3}和{3,2,1}哈希值不同。元素类型必须可哈希
boost::hash<T>必须支持容器内元素类型,否则编译报错。自定义类型需实现
boost::hash_value或operator()
否则hash_range无法生成哈希。用于 unordered_map/set
当容器或自定义类型作为键时非常有用,尤其是 vector/list 等非原生类型。效率考虑
对大型区间调用hash_range可能较慢,如果需要频繁查询,可以缓存哈希值。
6. 总结
boost::hash_range是一个非常方便的工具:
- 对区间内容生成哈希值
- 顺序敏感
- 可以轻松用于自定义类型的哈希映射
它的常见应用场景:
- 将
std::vector、std::list等容器放入unordered_map/unordered_set - 自定义结构体或组合类型哈希
- 配合 Boost 提供的
hash_combine与其他哈希策略进行复杂对象哈希