STL源码阅读(六) (SGI STL v3.3)
type_traits.h (<type_traits> C++11)
提供编译时类型信息,C++标准直到C++11才正式支持。SGI type_traits.h
提供的编译时类型信息很少,
只提供了_Is_integer
判断一个类型是否是整型(bool, char, signed char, unsigned char, wchar_t,
short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long),
以及提供了对是否是POD 类型的判断,是否有普通的(trivial)默认构造函数,拷贝构造函数,赋值构造函数和
析构函数。
stl_function.h (<functional>)
unary_function:用来创建单参数函数对象的基类。
binary_function:用来创建双参数函数对象的基类。
plus,minus,multiplies,divides,modulus,negate:算术运算函数对象。
euqal_to,not_equal_to,greater,less,greater_equal,less_equal:关系运算函数对象。
logical_and,logical_or,logical_not:逻辑运算函数对象。
unary_negate,binary_negate:仿函数,取反器。
not1,not2:生成取反器。
binder1st,binder2nd:仿函数,一元函数绑定器,由一个二元函数和一个参数绑定得到一个一元函数。
bind1st,bind2st:生成一元函数绑定器。
unary_compose,binary_compose:非标准。仿函数,函数组合器。
compose1,compose2:生成函数组合器。
pointer_to_unary_function,pointer_to_binary_function:仿函数,指向一元函数,二元函数的指针。
ptr_fun:返回pointer_to_binary_function和pointer_to_unary_function。
select1st,select2nd:非标准。返回二元组pair的元素。
project1st,project2nd,constant_void_fun,constant_unary_fun,constant_binary_fun,
constant0,constant1,constant2,subtractive_rng:非标准。提供这些函数,并没有多大意义。
mem_fun_t,const_mem_fun_t,mem_fun_ref_t,const_mem_fun_ref_t,
mem_fun1_t,const_mem_fun1_t,mem_fun1_ref_t,const_mem_fun1_ref_t:成员函数指针包装器。
mem_fun,mem_fun_ref,mem_fun1,mem_fun1_ref:生成成员函数指针包装器。
stl_tree.h
红黑树的实现(以下知识摘于算法导论),用来实现关联容器(set, map, multiset, multimap)。
红黑树的性质:
红黑树是一颗二叉搜索树,它在每一个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过
对任何一条从根节点到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长处2倍,
因而是近似平衡的。
一颗红黑树是满足下面红黑性质的二叉搜索树:
1. 每个结点要么是红色的,要么是黑色的。
2. 根节点是黑色的。
3. 每个叶节点(NIL)是黑色的(常常使用一个哨兵结点表示叶节点,或省略此哨兵结点)。
4. 如果一个结点是红色的,则它的两个子结点都是黑色的。
5. 对每个结点,从该结点到所有后代叶节点的简单路径上,均包含相同数目的黑色结点。
// 注意stl_tree所实现的红黑树的树的形式的一些小区别:
// (1) 头结点不仅指向树根结点,还指向树的最左边的那个结点,以及树的最右边的那个结点。
// (2) 当要删除的结点有两个孩子时,那么的后继结点重新调整位置链接到被删除结点的位置,而不是将后继结点拷贝到这个位置
// 红黑树颜色约束
typedef bool _Rb_tree_Color_type;
const _Rb_tree_Color_type _S_rb_tree_red = false;
const _Rb_tree_Color_type _S_rb_tree_black = true;
// 红黑树结点
struct _Rb_tree_node_base
{
typedef _Rb_tree_Color_type _Color_type;
typedef _Rb_tree_node_base* _Base_ptr;
_Color_type _M_color;
_Base_ptr _M_parent;
_Base_ptr _M_left;
_Base_ptr _M_right;
static _Base_ptr _S_minimum(_Base_ptr __x)
{
while (__x->_M_left != 0) __x = __x->_M_left;
return __x;
}
static _Base_ptr _S_maximum(_Base_ptr __x)
{
while (__x->_M_right != 0) __x = __x->_M_right;
return __x;
}
};
template <class _Value>
struct _Rb_tree_node : public _Rb_tree_node_base
{
typedef _Rb_tree_node<_Value>* _Link_type;
_Value _M_value_field;
};
// 红黑树迭代器(_Rb_tree_iterator),迭代器类型双向迭代器
_Self& operator++() { _M_increment(); return *this; }
// 红黑树是一棵二叉搜索树,对任何结点x,其左子树的中的关键字最大不超过x.key,
// 其右子树中的关键字最小不低于x.key
void _M_increment() { // operator++的实现
// 迭代到比当前结点大的所有结点的中的最小的那个结点
// 如果右子树存在,那么就是右子树最左边的叶子结点
if (_M_node->_M_right != 0) {
_M_node = _M_node->_M_right;
while (_M_node->_M_left != 0)
_M_node = _M_node->_M_left;
}
else {
// 当前结点不存在右子树时,且当前结点是父结点右结点时。那么,
// 一直上溯到其不为右节点为止
_Base_ptr __y = _M_node->_M_parent;
while (_M_node == __y->_M_right) { // 一直迭代到_M_node不是__y的右子树为止
_M_node = __y;
__y = __y->_M_parent;
}
// 当_M_node本身就是个左结点时,那么其父结点便是++迭代到的下一个结点
// 当_M_node是树最右边的一条边上结点时,_M_node就是树的根结点
// 当_M_node不是树最右边的一条边上结点时,_M_node就是上面while迭代到的__y
if (_M_node->_M_right != __y)
_M_node = __y;
}
}
_Self& operator--() { _M_decrement(); return *this; }
void _M_decrement() {
// 当前树只有两层的情况,且当前结点为叶节点。考虑状况(1)。
if (_M_node->_M_color == _S_rb_tree_red &&
_M_node->_M_parent->_M_parent == _M_node)
_M_node = _M_node->_M_right;
else if (_M_node->_M_left != 0) { // 左子树存在,那么--迭代的下一个结点便是左子树最大的那个结点
_Base_ptr __y = _M_node->_M_left;
while (__y->_M_right != 0)
__y = __y->_M_right;
_M_node = __y;
}
else {
// 当前结点即非根节点,亦不存在左子树。那么,迭代的下一个结点要么是其父结点(本身是个右节点),
// 要么是左结点第一个非右节点的父结点
_Base_ptr __y = _M_node->_M_parent;
while (_M_node == __y->_M_left) {
_M_node = __y;
__y = __y->_M_parent;
}
_M_node = __y;
}
}
// 旋转
// | |
// y <--------rotate_left----- x
// / /
// x c ---------rotate_right----> a y
// / /
// a b b c
// 在结点__x做左旋
inline void _Rb_tree_rotate_left(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
{
_Rb_tree_node_base* __y = __x->_M_right;
__x->_M_right = __y->_M_left;
if (__y->_M_left !=0)
__y->_M_left->_M_parent = __x;
__y->_M_parent = __x->_M_parent;
if (__x == __root)
__root = __y;
else if (__x == __x->_M_parent->_M_left)
__x->_M_parent->_M_left = __y;
else
__x->_M_parent->_M_right = __y;
__y->_M_left = __x;
__x->_M_parent = __y;
}
// 在结点__x做右旋
inline void _Rb_tree_rotate_right(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
{
_Rb_tree_node_base* __y = __x->_M_left;
__x->_M_left = __y->_M_right;
if (__y->_M_right != 0)
__y->_M_right->_M_parent = __x;
__y->_M_parent = __x->_M_parent;
if (__x == __root)
__root = __y;
else if (__x == __x->_M_parent->_M_right)
__x->_M_parent->_M_right = __y;
else
__x->_M_parent->_M_left = __y;
__y->_M_right = __x;
__x->_M_parent = __y;
}
// 插入结点后,红黑树性质的维护
// 分为两种情况,所插入的结点的父结点为左结点的情况,和为右节点的情况。
// 而每种又分为三种情景,见下面代码注释
// __x新插入的结点
inline void _Rb_tree_rebalance(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
{
__x->_M_color = _S_rb_tree_red;
// 只有插入位置的父结点的颜色为红色时,红黑树的性质才会改变
while (__x != __root && __x->_M_parent->_M_color == _S_rb_tree_red) {
// 插入位置的父结点是左结点
if (__x->_M_parent == __x->_M_parent->_M_parent->_M_left) {
_Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_right;
if (__y && __y->_M_color == _S_rb_tree_red) { // 叔结点颜色是红色时
__x->_M_parent->_M_color = _S_rb_tree_black; // 将父结点的颜色变为黑色
__y->_M_color = _S_rb_tree_black; // 将叔结点的颜色变为黑色
__x->_M_parent->_M_parent->_M_color = _S_rb_tree_red; // 将父结点的父结点的颜色变为红色
__x = __x->_M_parent->_M_parent; // 待旋转结点
}
else {
if (__x == __x->_M_parent->_M_right) { //待旋转结点的父结点是红色的,且是右结点时多做一次左旋
__x = __x->_M_parent;
_Rb_tree_rotate_left(__x, __root);
}
__x->_M_parent->_M_color = _S_rb_tree_black;
__x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
_Rb_tree_rotate_right(__x->_M_parent->_M_parent, __root); // 右旋
}
}
else { // 插入位置的父结点是右结点时,旋转操作和上面对称
_Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_left;
if (__y && __y->_M_color == _S_rb_tree_red) {
__x->_M_parent->_M_color = _S_rb_tree_black;
__y->_M_color = _S_rb_tree_black;
__x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
__x = __x->_M_parent->_M_parent;
}
else {
if (__x == __x->_M_parent->_M_left) {
__x = __x->_M_parent;
_Rb_tree_rotate_right(__x, __root);
}
__x->_M_parent->_M_color = _S_rb_tree_black;
__x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
_Rb_tree_rotate_left(__x->_M_parent->_M_parent, __root);
}
}
}
__root->_M_color = _S_rb_tree_black;
}
// 删除结点,红黑树性质的维护
// __z待删除结点
inline _Rb_tree_node_base* _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* __z,
_Rb_tree_node_base*& __root,
_Rb_tree_node_base*& __leftmost,
_Rb_tree_node_base*& __rightmost) {
_Rb_tree_node_base* __y = __z;
_Rb_tree_node_base* __x = 0;
_Rb_tree_node_base* __x_parent = 0;
if (__y->_M_left == 0) // __z has at most one non-null child. y == z.
__x = __y->_M_right; // __x might be null.
else
if (__y->_M_right == 0) // __z has exactly one non-null child. y == z.
__x = __y->_M_left; // __x is not null.
else { // __z has two non-null children. Set __y to
__y = __y->_M_right; // __z's successor. __x might be null.
while (__y->_M_left != 0)
__y = __y->_M_left;
__x = __y->_M_right;
}
if (__y != __z) { // relink y in place of z. y is z's successor
__z->_M_left->_M_parent = __y;
__y->_M_left = __z->_M_left;
if (__y != __z->_M_right) {
__x_parent = __y->_M_parent;
if (__x) __x->_M_parent = __y->_M_parent;
__y->_M_parent->_M_left = __x; // __y must be a child of _M_left
__y->_M_right = __z->_M_right;
__z->_M_right->_M_parent = __y;
}
else
__x_parent = __y;
if (__root == __z)
__root = __y;
else if (__z->_M_parent->_M_left == __z)
__z->_M_parent->_M_left = __y;
else
__z->_M_parent->_M_right = __y;
__y->_M_parent = __z->_M_parent;
__STD::swap(__y->_M_color, __z->_M_color);
__y = __z;
// __y now points to node to be actually deleted
}
else { // __y == __z
__x_parent = __y->_M_parent;
if (__x) __x->_M_parent = __y->_M_parent;
if (__root == __z)
__root = __x;
else
if (__z->_M_parent->_M_left == __z)
__z->_M_parent->_M_left = __x;
else
__z->_M_parent->_M_right = __x;
if (__leftmost == __z)
if (__z->_M_right == 0) // __z->_M_left must be null also
__leftmost = __z->_M_parent;
// makes __leftmost == _M_header if __z == __root
else
__leftmost = _Rb_tree_node_base::_S_minimum(__x);
if (__rightmost == __z)
if (__z->_M_left == 0) // __z->_M_right must be null also
__rightmost = __z->_M_parent;
// makes __rightmost == _M_header if __z == __root
else // __x == __z->_M_left
__rightmost = _Rb_tree_node_base::_S_maximum(__x);
}
if (__y->_M_color != _S_rb_tree_red) { //
while (__x != __root && (__x == 0 || __x->_M_color == _S_rb_tree_black))
if (__x == __x_parent->_M_left) {
_Rb_tree_node_base* __w = __x_parent->_M_right;
if (__w->_M_color == _S_rb_tree_red) {
__w->_M_color = _S_rb_tree_black;
__x_parent->_M_color = _S_rb_tree_red;
_Rb_tree_rotate_left(__x_parent, __root);
__w = __x_parent->_M_right;
}
if ((__w->_M_left == 0 ||
__w->_M_left->_M_color == _S_rb_tree_black) &&
(__w->_M_right == 0 ||
__w->_M_right->_M_color == _S_rb_tree_black)) {
__w->_M_color = _S_rb_tree_red;
__x = __x_parent;
__x_parent = __x_parent->_M_parent;
} else {
if (__w->_M_right == 0 ||
__w->_M_right->_M_color == _S_rb_tree_black) {
if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;
__w->_M_color = _S_rb_tree_red;
_Rb_tree_rotate_right(__w, __root);
__w = __x_parent->_M_right;
}
__w->_M_color = __x_parent->_M_color;
__x_parent->_M_color = _S_rb_tree_black;
if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;
_Rb_tree_rotate_left(__x_parent, __root);
break;
}
} else { // same as above, with _M_right <-> _M_left.
_Rb_tree_node_base* __w = __x_parent->_M_left;
if (__w->_M_color == _S_rb_tree_red) {
__w->_M_color = _S_rb_tree_black;
__x_parent->_M_color = _S_rb_tree_red;
_Rb_tree_rotate_right(__x_parent, __root);
__w = __x_parent->_M_left;
}
if ((__w->_M_right == 0 ||
__w->_M_right->_M_color == _S_rb_tree_black) &&
(__w->_M_left == 0 ||
__w->_M_left->_M_color == _S_rb_tree_black)) {
__w->_M_color = _S_rb_tree_red;
__x = __x_parent;
__x_parent = __x_parent->_M_parent;
} else {
if (__w->_M_left == 0 ||
__w->_M_left->_M_color == _S_rb_tree_black) {
if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;
__w->_M_color = _S_rb_tree_red;
_Rb_tree_rotate_left(__w, __root);
__w = __x_parent->_M_left;
}
__w->_M_color = __x_parent->_M_color;
__x_parent->_M_color = _S_rb_tree_black;
if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;
_Rb_tree_rotate_right(__x_parent, __root);
break;
}
}
if (__x) __x->_M_color = _S_rb_tree_black;
}
return __y;
}
template <class _Key, class _Value, class _KeyOfValue, class _Compare, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Value) >
class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc>;
// _Rb_tree中维护了一个_M_header指向树的header结点
// 另外维护了_M_node_count记录树的大小
// 上面已经列出了红黑树的性质破坏时,正确维护它们的函数。其它增删改查就很容易实现了。