C++ | pair 作为 unordered_map unordered_set 的键值 最佳实现模版

今天在做一道AtCoder的题目,有个test case一直TLE。研究这个测试用例和其他用例的区别,苦思不得其解。后来把unordered_map换成map就过了。虽然在小数据集上hashmap和treemap区别不大,但数据量大的话,hashmap还是好些。所以最佳实践是,在不需要排序特性时,就用hashmap。
而且之前也从来没有遇到过hashmap比treemap效果差这么多的原因。最后花了一上午时间,才定位到是我的 pair 的hash函数实现太糟糕了。因为C++ STL中并没有pair的hash特化,所以如果想把pair当作键用在unordered_map中的话,就需要自己实现hash函数。我直接从网上抄了一个实现, 直接将 std::hash<T>()(pair.first) ^ std::hash<U>()(pair.second)。为了避免误人子弟,我就不贴代码了。正是抄的这个实现害苦我了,hash函数碰撞严重,导致效率低下。令人惊讶的是,这种错误的实现遍布全网,无论是中文的还是英文的。我从犄角旮旯(stackoverflow问题的评论区中)里才找到问题所在和正确的实现。所以特意总结此博文,避免更多的同学踩坑。

std::hash()(x.first) ^ std::hash()(x.second); - that’s a spectacularly collision-prone way to hash a pair, as every pair with two identical value hashes to 0, and every pair {a, b} hashes the same as {b, a}. For vaguely demanding use, much better to find a hash_combine function and employ that.

惊讶的是,一看到这个评论,我就像中电一样。忽然记起,多年前,当我还是一只小白时,读《C++ 标准库(第二版)》时,作者就已经给出了绝佳的解决方案。我匆忙翻出珍藏的《C++ 标准库(第二版)》的unordered_map对应章节,“7.9.2 Creating and Controlling Unordered Container",把任意结构hash化的代码搬出来,模版如下:

#include <functional>
// from boost (functional/hash):
// see http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html template
template <typename T>
inline void hash_combine
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值