STL源码阅读(六)
2016-08-05 12:21
330 查看
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记录树的大小 // 上面已经列出了红黑树的性质破坏时,正确维护它们的函数。其它增删改查就很容易实现了。
参考资料
sgi STLcppreference.com
算法导论 Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein
CSDN KangRoger的专栏
相关文章推荐
- STL源码阅读(三)
- STL源码阅读(四)
- STL源码阅读(七)
- 迭代器的型别 《STL 源码剖析》阅读笔记
- STL源码阅读 -- basic_string
- STL源码阅读(五)
- SGI_STL slist 源码阅读笔记
- STL源码阅读(八)
- STL源码阅读-allocator
- STL源码阅读-红黑树(RB-tree)、AVL树、AA树
- STL 源码阅读
- STL源码阅读-deque
- STL源码阅读(一)
- STL源码阅读(九)
- STL源码阅读-hashtable
- STL源码阅读-list
- STL源码阅读-iterator
- STL源码阅读(二)
- STL源码阅读-vector
- SGI STL 源码阅读和分析 (1)