STL源码剖析(四):容器(6)Rb_tree

之前讲的都是序列式容器,现在开始进入到关联式容器,关联式容器主要以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寻找。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值