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

本文讲述了作者在使用 C++ 的 unordered_map 时遇到性能问题,由于 pair 的默认 hash 函数导致效率低下。通过深入研究,作者发现了问题所在,即简单的 XOR 操作造成了严重的哈希冲突。文中引用了《C++ 标准库(第二版)》中的解决方案,提供了一个更好的 hash_pair 模板,并强调了深入学习和理解的重要性,而不仅仅是依赖复制粘贴解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在做一道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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值