C++STL unordered_map/set 复杂类型hash

写题的时候经常要判断一个区间或者一条边/点是否存在。会写出这种代码

unordered_map<pair<int, int>, int>m1;
unordered_map<node, int>m2;

很明显报错了。理由是STL unordered_map/set只对基本数据类型和string做了hash。也就是不仅是自定义类型,pair这种的hash也要自己写。

首先来分析unordered_map/set的参数

unordered_set<typename _Kty,typename _Hasher=hash<_Kty>,typename _Keyeq=equal_to<_Kty>,typename _Allocator<_Kty>>
unordered_map<typename _Kty,typename _Value,typename _Hasher=hash<_Kty>,typename _Keyeq=equal_to<_Kty>,typename _Allocator<_Kty>>

以unordered_map为例,

前两个参数为(key,value)键值对。

第三个参数即为hash标准,

而第四个参数为判断元素相同的函数 因为map和set需要判断新加入元素和容器内元素的键值是否相同来安排元素的位置。

也就是说,我们需要一个仿函数实现该复杂类型的hash,同时还需要给这个类型重载==(equal)以至于map/set可以安排他的位置。

得到hash值可以通过STL自带的hash模板函数,但是只能对基本数据类型和string做hash。不过我们可以分解复杂类型内的基本类型,用复杂类型的基本类型组合成新的hash值代表这个复杂类型。

hash<typename>()(valua)

补充:所谓仿函数也就是重载在一个结构体/类中的运算符函数。

struct node {
	int x, y;
	int operator==(const node& a)const {//自定义类型要加==重载
		if(x==a.x&&y==a.y)
		return 1;
	}
};
struct hashf {
	template<class T,class U>
	int operator()(const pair<T, U>& a)const {
		return hash<int>()(a.first)*13 ^ hash<int>()(a.second)*31;
	}

	int operator()(const node& a)const {
		return hash<int>()(a.x)*13 ^ hash<int>()(a.y)*31;//基本类型组合成新的hash
	}
};
unordered_map<pair<int, int>, int,hashf>m1;
unordered_map<node, int, hashf>m2;

这样就可以实现,对pair和自定义类型的hash了

注意,如果hash函数太弱的的话会频繁产生hash冲突,复杂度会大幅提高。


但是map和set不需要这么麻烦,map可以直接存入pair,是因为,map和set只需要重载比较运算符进行排序,而unordered_map底层是hash表,所以需要hash值。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值