news 2026/5/10 5:07:27

红黑树解析:map与set底层原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
红黑树解析:map与set底层原理

红黑树解析:C++ STL 中 map 与 set 的底层原理

在 C++ STL 中,std::setstd::mapstd::multisetstd::multimap这四个关联式容器,底层几乎全部使用红黑树(Red-Black Tree)实现(主流实现如 libstdc++、libc++ 都是如此)。

红黑树是一种自平衡二叉搜索树,它在插入/删除后通过颜色调整和旋转操作,始终保证树的高度接近 log n,从而让查找、插入、删除的时间复杂度稳定在O(log n)

1. 为什么选择红黑树?

数据结构查找插入删除顺序遍历内存占用自平衡难度STL 选择理由
普通二叉树O(n)O(n)O(n)O(n)中等最坏退化严重
AVL 树O(log n)O(log n)O(log n)O(n)中等高(旋转多)旋转次数多,工程复杂
红黑树O(log n)O(log n)O(log n)O(n)中等中等平衡性好,旋转次数少,常用于工程
B+ 树O(log n)O(log n)O(log n)O(n)复杂更适合数据库/文件系统
哈希表O(1)O(1)O(1)无序无序,无法实现有序容器

结论:红黑树在平衡性、插入/删除代价、实现复杂度三者之间取得了最佳折中,非常适合 STL 的有序关联容器。

2. 红黑树的五大性质(必须死记)

红黑树是一棵二叉搜索树+颜色约束

  1. 节点颜色:每个节点要么是红色,要么是黑色。
  2. 根节点:根节点是黑色
  3. 叶子节点(NIL/null 节点):所有叶子节点(包括空节点)都是黑色
  4. 红色节点规则红色节点的子节点必须是黑色(即不能出现红红相连)。
  5. 黑色高度:从任意节点到其每个叶子节点的路径上,黑色节点数量相同(黑色高度相同)。

这五条性质共同保证了:最长路径不超过最短路径的 2 倍,从而树高 ≈ log n。

3. STL 中红黑树的节点结构(简化版)

struct_Rb_tree_node_base{typedef_Rb_tree_node_base*base_ptr;base_ptr parent,left,right;_Rb_tree_color color;// 枚举:_S_red, _S_black};template<typenameValue>struct_Rb_tree_node:public_Rb_tree_node_base{Value value_field;// 真正存储的数据};
  • map中 Value =std::pair<const Key, T>
  • set中 Value =Key(或者说 set 把 key 当 value)

4. map 与 set 的区别(核心差异在 KeyOfValue)

STL 通过模板参数萃取技巧,让同一棵红黑树同时支持 map / set / multimap / multiset。

// 伪代码风格(简化)template<typenameKey,typenameValue,typenameKeyOfValue,// 关键差异点!typenameCompare=less<Key>,typenameAlloc=allocator<Value>>class_Rb_tree{// ...};// set 的 KeyOfValuestruct_Identity{template<typenameT>constT&operator()(constT&x)const{returnx;}};// map 的 KeyOfValuestruct_Select1st{template<typenamePair>consttypenamePair::first_type&operator()(constPair&x)const{returnx.first;}};

一句话总结差异

容器允许 key 重复?元素类型本质KeyOfValue 萃取方式插入行为
setKey返回元素本身重复不插入
multisetKey返回元素本身允许重复
map否(key 唯一)pair<const Key, T>返回 pair.first (key)key 重复不插入([] 会覆盖)
multimappair<const Key, T>返回 pair.first (key)允许 key 重复

5. 红黑树的核心操作(插入/删除)

插入(大致流程):

  1. 按二叉搜索树规则插入新节点(新节点默认红色
  2. 如果父节点是红色 → 违反“红红不能相连” → 需要调整
  3. 调整方式:变色 + 左旋 / 右旋(最多 O(log n) 次旋转)
  4. 最终保证根是黑色、没有红红相连、黑色高度一致

删除(更复杂):

  1. 找到后继节点替换(或直接删除)
  2. 如果被删节点是黑色 → 可能破坏黑色高度
  3. 通过借颜色旋转变色修复(最多 O(log n) 次操作)

STL 的实现非常精巧,使用了大量模板元编程内联函数来减少开销。

6. 时间复杂度对比表(最常用操作)

操作set / multisetmap / multimapunordered_set / unordered_map
查找(find)O(log n)O(log n)平均 O(1),最坏 O(n)
插入(insert)O(log n)O(log n)平均 O(1),最坏 O(n)
删除(erase)O(log n)O(log n)平均 O(1),最坏 O(n)
顺序遍历O(n)O(n)O(n)(无序)
按 key 排序

7. 面试/实战高频问题

  1. map 和 set 为什么用红黑树而不是 AVL 树?
    → 红黑树插入/删除时的旋转次数更少(工程上更高效),虽然 AVL 更平衡,但维护代价高。

  2. map 的 [] 运算符为什么会插入新元素?
    → 因为返回的是mapped_type&,如果 key 不存在会默认构造 value 并插入。

  3. multimap 如何实现 key 重复?
    → 红黑树插入时不检查相等性,只按 < 排序,允许相同 key 连续存放。

  4. 为什么 map 的 key 是 const 的?
    → 防止修改 key 破坏红黑树排序规则。

  5. 红黑树和 B+ 树的主要区别?
    → 红黑树是内存结构(每个节点只存少量数据),B+ 树是磁盘友好结构(叶子存数据,非叶子只存索引)。

总结一句话

C++ STL 中的 set / map / multiset / multimap 底层都是红黑树,通过KeyOfValue 萃取比较器的模板技巧,实现了有序性唯一性/可重复性的差异,在O(log n)的复杂度下提供了高效的键值关联存储能力。

如果你想继续深入以下任一方向,告诉我:

  • 红黑树插入/删除的详细步骤 + 旋转图解
  • 自己手写一个简易版红黑树(带 set/map 接口)
  • map 与 unordered_map 的性能对比场景
  • STL 源码中 _Rb_tree 的关键实现细节

随时说~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 1:39:24

免费vs付费AIGC工具:10款主流选项性能对比

&#xfffd;&#xfffd; 10大降AIGC平台核心对比速览 排名 工具名称 降AIGC效率 适用场景 免费/付费 1 askpaper ⭐⭐⭐⭐⭐ 学术论文精准降AI 付费 2 秒篇 ⭐⭐⭐⭐⭐ 快速降AIGC降重 付费 3 Aibiye ⭐⭐⭐⭐ 多学科论文降AI 付费 4 Aicheck ⭐⭐⭐⭐…

作者头像 李华
网站建设 2026/5/9 20:23:43

发展融、民生暖:首都都市圈协同规划的幸福密码

“这么近、那么美&#xff0c;周末到河北”&#xff0c;这句朗朗上口的旅游口号&#xff0c;正是京津冀老百姓的真实生活写照。 从北京出发&#xff0c;半小时去天津吃狗不理包子&#xff0c;1小时去张家口滑雪&#xff0c;1.5小时到承德避暑山庄&#xff0c;2小时奔赴秦皇岛看…

作者头像 李华
网站建设 2026/5/3 11:25:54

特殊函数(贝塞尔函数....)

要贯穿整个特殊函数的发展史&#xff0c;最好的例子莫过于**“振动”**这一物理现象。 我们可以通过圆鼓皮的振动&#xff08;或地震点源激发的波&#xff09;这一主线&#xff0c;看人类是如何从“解决一个具体麻烦”演进到“建立一套宇宙对称性语言”的。 第一阶段&#xf…

作者头像 李华
网站建设 2026/5/1 5:07:13

【Linux】du 命令查看文件和目录的磁盘占用

du 命令详解&#xff1a;查看文件和目录的磁盘占用 du&#xff08;disk usage&#xff09;是 Linux 中最常用的查看磁盘空间占用情况的命令之一。它可以统计文件、目录甚至整个文件系统的实际占用空间&#xff0c;非常适合排查“磁盘满了”“哪个目录吃空间”等场景。 下面从…

作者头像 李华
网站建设 2026/5/1 7:22:00

宏智树AI封神科普:论文数据分析零门槛,小白也能做出硬核实证

作为深耕论文写作科普的博主&#xff0c;后台每天都被粉丝的求助刷屏&#xff1a;“收集了300份问卷&#xff0c;却卡在SPSS操作上动不了”“跑出来的回归结果看不懂&#xff0c;不知道怎么支撑论文论点”“理工科实验数据一堆&#xff0c;手动整理算错好几次&#xff0c;越改越…

作者头像 李华
网站建设 2026/5/8 9:05:59

一起来围观Anthropic官方万的AI Agent评估方法论

前言在传统软件开发中&#xff0c;我们习惯于“写代码 → 写测试 → 验证通过”的线性流程。测试用例是确定的&#xff0c;输出是可预测的&#xff0c;失败意味着 bug&#xff0c;成功意味着正确。但当我们转向 AI Agent 开发时&#xff0c;这套逻辑突然失效了。Agent 不再是一…

作者头像 李华