0

0

C++里的std::map和std::unordered_map哪个更快?(红黑树O(logN)与哈希表O(1))

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-23 17:15:10

|

479人浏览过

|

来源于php中文网

原创

std::unordered_map平均查找O(1)但可能退化至O(N),std::map稳定O(log N);前者适合高质量哈希、均匀分布、预分配且只读场景,后者适合有序遍历、范围查询或小数据量。

c++里的std::map和std::unordered_map哪个更快?(红黑树o(logn)与哈希表o(1))

std::map 查找慢但稳定,std::unordered_map 平均快但有退化风险

直接说结论:std::unordered_map 平均查找是 O(1)std::mapO(log N),但“平均”二字很关键——std::unordered_map 在哈希碰撞严重时会退化到 O(N),而 std::mapO(log N) 始终可预测。

什么时候 std::unordered_map 真正快?

它快的前提是:键类型有高质量哈希函数、负载因子合理、内存足够、无大量重复哈希值。实际中常见满足条件的场景:

  • intstd::string(短字符串,且编译器启用了 SSO)、std::pair(自定义哈希已正确实现)
  • 插入后基本只读查,不频繁增删导致 rehash
  • 容器大小在千级到百万级,且键分布较均匀
  • 你调用了 reserve() 预分配桶数,避免多次 rehash

没做 reserve() 时,插入过程可能触发多次扩容 + 全量重哈希,反而比 std::map 更慢。

std::map 哪些情况反而更优?

红黑树结构天然支持有序遍历和范围查询,这是哈希表做不到的。如果你需要:

立即学习C++免费学习笔记(深入)”;

Axiom
Axiom

Axiom是一个浏览器扩展,用于自动化重复任务和web抓取。

下载
  • 按 key 升序/降序迭代(for (const auto& p : my_map) 就是有序的)
  • lower_bound() / upper_bound() 找区间,或 equal_range()
  • 键类型难写靠谱哈希(比如自定义结构体,字段多、易出错),或哈希函数本身慢(如长字符串反复计算)
  • 数据量小(N ),log N ≈ 6,而哈希计算+取模+指针跳转开销可能更高

另外,std::map 迭代器稳定(插入不使原有迭代器失效),std::unordered_map 一旦 rehash,所有迭代器全失效——这对某些算法逻辑是硬伤。

别忽略内存与局部性差异

哈希表空间利用率低:默认最大负载因子是 1.0,意味着至少一半桶为空;且节点分散在堆上,缓存不友好。红黑树节点虽也有指针开销,但通常连续插入时内存布局更紧凑。

实测常见陷阱:

  • std::string 作 key 时,短串(≤23 字节)走 SSO,哈希快;长串每次调用 std::hash<:string> 会遍历整个字符串,开销陡增
  • 自定义类型没重载 operator== 或没提供 std::hash 特化,编译直接报错,不是运行慢
  • 调试模式下 std::unordered_map 的调试检查(如桶链表完整性验证)会显著拖慢,误判为“性能差”
std::unordered_map m;
m.reserve(1024); // 推荐:提前预留,避免运行时扩容
for (int i = 0; i < 1000; ++i) {
    m[i] = i * 2;
}

真正决定快慢的从来不是大 O 标签,而是你的键分布、操作模式、编译器优化级别,以及是否忘了 reserve 或写错了哈希。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

358

2023.08.02

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

527

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

278

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1492

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

622

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

552

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

566

2024.04.29

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4.8万人学习

Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号