从红黑树到 map/set:一次完整的 STL 容器模拟实现
在继续之前,最好你已经知道红黑树的基本操作。这篇笔记记录的是:给定一个能跑的通的红黑树结构,如何把它封装成 std::set 和 std::map 那样的容器。
STL 里的那点模板把戏
看 set 的模板参数,红黑树部分传了两个 Key:
template<class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
typedef rb_tree<Key, Key, identity<Key>, key_compare, Alloc> rep_type;
rep_type t;
};
多传一个重复的类型,为的是和 map 的模板参数保持一致,让底层红黑树能复用同一份代码。map 传的是 pair<const Key, T>:
template<class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
typedef rb_tree<Key, pair<const Key, T>, select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t;
};
所以红黑树节点实际存的数据是泛化的 T,set 是 Key,map 是 pair。而第一个模板参数 Key 独立出来,方便 find 这类接口定义参数类型。
红黑树迭代器:按中序遍历走
为了支持容器遍历,我们需要给红黑树做一个迭代器。它本质上就是对节点指针的包装。
节点定义我改成这样,_data 存的是 T:
template<typename T>
struct RBTreeNode {
T _data;
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Colour _col;
};
然后树的类模板改成 template<typename K, typename T> class RBTree,节点用 RBTreeNode<T>。
迭代器需要实现 返回数据引用, 返回数据地址,以及递增和递减按照中序遍历逻辑移动。


