C++ 的两个参考文档
非官方文档:cplusplus
官方文档:cppreference
1. 分析:源码及框架
封装红黑树的难点通常不在于核心逻辑,而在于整体结构设计。通过对比 STL 源码,我们可以更好地理解泛型编程在其中的应用。
1.1 见一见源码
建议参考中间版本的源码(如 SGI STL 30 版本),最新源码经过多年优化可能过于复杂。主要关注 stl_tree.h、stl_map.h、stl_set.h 等文件。
1.2 对比 set 和 map 的源码:泛型编程的应用
虽然底层都基于红黑树,但模板参数设计有所不同。rb_tree 类模板的第一个参数是 Key,第二个参数是 Value。
- set:实例化时第二个参数为
Key,节点存储的就是 Key。 - map:实例化时第二个参数为
pair<const Key, T>,节点存储的是键值对。
这种设计使得同一棵红黑树结构可以支持不同的容器场景。第一个模板参数 Key 主要用于 find、erase 等函数的形参类型,而第二个参数 Value 决定了节点内部存储的数据类型。
注意源码中 value_type 的定义:它指的是红黑树节点中存储的真实数据类型,而非我们日常理解的 Value。对于 map,value_type 是 pair<const K, V>;对于 set,则是 K。
2. map 和 set 的模拟实现
2.1 复用红黑树的框架
参考源码框架,map 和 set 均复用 RBTree。为了适配不同场景,我们在 map 和 set 层分别实现了 MapKeyOfT 和 SetKeyOfT 仿函数,传给 RBTree 的 KeyOfT 参数。
RBTree 通过 KeyOfT 从存储的 T 类型对象中提取 Key 进行比较。这样无论节点存的是 K 还是 pair<K, V>,都能正确比较 Key。
// 示例:仿函数定义
struct {
{
kv.first;
}
};


