本章我们总共学习无序关联式容器:unordered_map容器、unordered_multimap容器、unordered_set容器、unordered_multiset容器,他们的底层都是基于哈希表的结构封装起来的一个类。在存储基础数据类型时,键(key)能够通过哈希函数转为哈希值(数据类型为size_t),当我们的键为自定义数据类型时,就需要我们重新定义哈希函数和重载operator'=='运算符。哈希函数一般是通过仿函数来实现的。仿函数重写哈希函数时,要求我们的哈希函数能够让键均匀分布、确定是唯一的键和方便计算,一般是通过位移异或组合法来合成哈希值的。下面让我们通过unordered_map容器来装user结构体,具体分析如何重载“==”和重写哈希函数:

#include<iostream>
#include<string>
#include<unordered_map>
/*自定义哈希函数*/
using namespace std;
struct user
{
bool operator==(const user&u)const//const不能丢 
{
return m_s==u.m_s&&m_age==u.m_age&&m_gender==u.m_gender;
}
user(string s,int age,string gender):m_s(s),m_age(age),m_gender(gender){};
string m_s;
int m_age;
string m_gender;
};
struct fhash
{
size_t operator()(const user&u)const
{
/*组合所有字段的哈希值,让每个成员变量参与分配*/
size_t h1 = hash<string>{}(u.m_s);
size_t h2 = hash<int>{}(u.m_age);
size_t h3 = hash<string>{}(u.m_gender);
/*经典操作*/ 
/*通过'<<'位移和'^'按位异或,高效返回尽量“独立 ”的哈希值,避免哈希冲突*/
return  h1^(h2<<1)^(h3<<2);
        
}
};
void test()
{
unordered_map<user,int,fhash> ump;
ump.insert({{"dot01",18,"男"},1}); 
ump.insert({{"dot02",18,"男"},2});
ump.insert({{"dot03",18,"男"},3});
ump.insert({{"dot04",18,"男"},4});
ump.insert({{"dot05",18,"男"},5});
}
int main(){
    test();
    return 0;
}

代码成功编译!

总结:对于无序关联式容器,当键为自定义数据类型时,就需要我们重新定义哈希函数和重载operator'=='运算符,运算符重载不难,但是需要记住位移异或组合法来合成哈希值。

点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)