如何实现组合关键字的unordered_set/unordered_map
在VC编译器中,使用unordered_set或unordered_map时,如果需要将多个选项作为关键字进行hash,例如将学生信息中的学号和姓名相结合标记,应该如何实现呢?
STL库中提供了强大的hash function,该函数可以将数据进行hash,并将多个选项进行整合得到一个hash关键字,其实现如下。
#include <string>
#include <unordered_set>
#include <functional>
class hash_combine1{ // 这是一个仿函数,即重载了()操作符,可实现类似函数的操作的一种类型
public:
size_t operator()(const pair<string, int>&a) const{ // 两处const必须加
auto h1 = hash<string>()(a.first);
auto h2 = hash<int>()(a.second);
return h1 ^ h2; // 此处的操作可以自定义
}
};
size_t hash_combine2(pair<string, int>& a){
auto h1 = hash<string>()(a.first);
auto h2 = hash<int>()(a.second);
return h1 ^ h2;
}
int main()
{
unordered_set<pair<string, int>, hash_combine1>tab1;
tab1.insert({"123", 1});
tab1.emplace("124", 2); // 使用emplace会自动调用其构造函数
// 省去了拷贝构造的过程,效率更高
// unordered_set<pair<string, int>, hash_combine2>tab2; // 错误,传递的必须是仿函数
// 即传递一个类型名
// tab2.emplace("345", 2);
return 0;
}
其中的hash()模板函数具体实现不同编译器有所差异,可以打开function_hash.h文件查看。