卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
  • 本栏必读

    • 关于本专栏
    • C++学习路线
    • C++面试题系优化
  • 基础与语法

  • 面向对象

  • STL 与容器

    • STL容器了解哪些
    • STL中allocator的作用
    • STL中迭代器失效的场景
    • c++的map和unordered_map有什么区别和实现原理
    • map,deque,list的底层实现原理
      • 简要回答
      • 详细回答
      • 知识拓展
    • unordered_map的rehash机制
    • vector底层原理和扩容过程
    • push_back()和emplace_back()的区别
  • 内存管理

  • C++11 与现代 C++

  • 智能指针

  • 并发与 I/O

# map、deque、list 的底层实现

面试官问"map、deque、list 底层是怎么实现的",很多人只能说出"红黑树、数组、链表"——这只是开头。追问"deque 的随机访问怎么做到 O(1)"或"为什么 list 的缓存性能差"就答不上来了。

# 简要回答

map:底层是红黑树(自平衡二叉搜索树),键有序,插入/删除/查找都是 O(log n)。unordered_map 底层是哈希表,无序,平均 O(1)。

deque:底层是"分段连续存储"——一个中控数组(map)指向多个固定大小的缓冲区块。两端插入 O(1),随机访问 O(1)(两次计算:块索引 + 块内偏移)。

list:底层是双向链表,每个节点存前驱指针、后继指针和数据。任意位置插入/删除 O(1)(已知位置时),但不支持随机访问,遍历才能定位。

# 详细回答

map(红黑树)

红黑树保证最长路径不超过最短路径的两倍,所有操作 O(log n)。键自动有序(按 < 运算符或自定义比较器)。插入/删除不会导致其他迭代器失效——这是树结构的天然优势。unordered_map 用哈希表,桶+链表(或桶+红黑树),平均 O(1) 但最坏 O(n),rehash 时所有迭代器失效。

deque(分段连续存储)

核心结构:一个指针数组(中控 map),每个指针指向一个固定大小的连续缓冲区。push_front/push_back 只需在当前块的前/后填充,块满了就分配新块并在中控 map 中加一个指针。随机访问:先算目标在第几个块(偏移量 / 块大小),再算块内位置(偏移量 % 块大小),两次除法就定位了,所以是 O(1)。中间插入需要移动元素,O(n)。

list(双向链表)

每个节点独立分配,通过前驱/后继指针串联。已知迭代器位置时,插入/删除只需改指针,O(1)。但定位第 n 个元素必须从头遍历,O(n)。节点分散在堆上,缓存不友好(cache miss 多),这是 list 在现代硬件上性能差的主要原因。插入/删除不会导致其他迭代器失效。

选型对比

维度 map deque list
底层结构 红黑树 分段连续数组 双向链表
随机访问 不支持 O(1) 不支持
两端插入 O(log n) O(1) O(1)
中间插入 O(log n) O(n) O(1)(已知位置)
迭代器失效 删除当前才失效 头尾插入不失效,中间插入全失效 删除当前才失效
缓存友好 差 较好 差

map/deque/list底层结构

# 知识拓展

Q:为什么 deque 中间插入比 list 慢?

deque 中间插入需要移动元素来维持块内连续性,平均移动 n/2 个元素,还可能跨块移动。list 只需改两个指针,O(1) 恒定时间。但实际场景中,如果插入不频繁,deque 的缓存友好性带来的遍历优势远超 list。

Q:什么时候该用 list 而不是 deque?

两种情况:一是需要频繁在中间位置插入/删除(且已持有迭代器);二是需要迭代器/指针/引用在插入删除后不失效。除此之外,现代 C++ 中 deque 甚至 vector 几乎总是比 list 快,因为缓存局部性的优势太大了。

Q:map 和 unordered_map 怎么选?

需要键有序(范围查询、按序遍历)用 map;只需要快速查找/插入用 unordered_map。unordered_map 平均更快但最坏情况差,且 rehash 时所有迭代器失效;map 稳定 O(log n),迭代器几乎不失效。

Q:deque 能完全替代 vector 吗?

不能。deque 的内存不是完全连续的(分段连续),不能直接传给需要连续内存的 C API。vector 保证内存连续,可以用 data() 拿到裸指针。另外 vector 的缓存性能比 deque 更好(完全连续 vs 分段连续)。

Last Updated: 5/25/2026, 3:50:35 PM

← c++的map和unordered_map有什么区别和实现原理 unordered_map的rehash机制 →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪