之前讲的都是序列式容器,现在开始进入到关联式容器,关联式容器主要以Rb-tree和hash-table做为底层结构。
Rb-tree的节点设计
RB-tree结构和迭代器也是采用继承机制
节点结构
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迭代器
基础迭代器
struct _Rb_tree_base_iterator
{
typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
typedef bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
_Base_ptr _M_node;
// 找下一个节点,用于实际迭代器的++
void _M_increment()
{
// 如果有右子树,找右子树最左的元素
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;
__y = __y->_M_parent;
}
// 如果此时的右子节点不等于此时的父节点
if (_M_node->_M_right != __y)
_M_node = __y;
}
}
// 找前一个元素,用于实际迭代器-- 操作
void _M_decrement()
{
// 是红色节点,且父节点的父节点就是自己,也就是node就是header,因为root一定为黑
// 结合下图
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;
}
}
};
实际迭代器
template <class _Value, class _Ref, class _Ptr>
struct _Rb_tree_iterator : public _Rb_tree_base_iterator
{
typedef _Value value_type; // 迭代器的五种类型
typedef _Ref reference;
typedef _Ptr pointer;
typedef _Rb_tree_iterator<_Value, _Value&, _Value*>
iterator;
typedef _Rb_tree_iterator<_Value, const _Value&, const _Value*>
const_iterator;
typedef _Rb_tree_iterator<_Value, _Ref, _Ptr>
_Self;
typedef _Rb_tree_node<_Value>* _Link_type; // 指向rb_node
_Rb_tree_iterator() {}
_Rb_tree_iterator(_Link_type __x) { _M_node = __x; }
_Rb_tree_iterator(const iterator& __it) { _M_node = __it._M_node; }
reference operator*() const { return _Link_type(_M_node)->_M_value_field; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
_Self& operator++() { _M_increment(); return *this; }
_Self operator++(int) {
_Self __tmp = *this;
_M_increment();
return __tmp;
}
_Self& operator--() { _M_decrement(); return *this; }
_Self operator--(int) {
_Self __tmp = *this;
_M_decrement();
return __tmp;
}
};
Rb-tree的数据结构
和其他结构一样,首先是设置空间配置器和各种type,RB-tree有三个特殊的数据:
size_type node_count; // 树节点大小
link_type header; // 根节点前面再加一个节点,其颜色初始化为红色,以区分root
Compare key_compare; // 节点间键值大小的比较准则,是个函数对象。
函数
void _M_empty_initialize() {
_S_color(_M_header) = _S_rb_tree_red; // 令header为红色
_M_root() = 0;
_M_leftmost() = _M_header; // 令header的左右子节点为自己
_M_rightmost() = _M_header;
}
元素插入分为两种:元素可重复(insert_equal)和元素不可重复(insert_unique)
元素平衡操作:考虑两个因素,旋转和颜色
元素的查找:根据key_compare寻找。