STL源码剖析(十三)关联式容器之RB-tree(红黑树)设计

RB-tree节点和迭代器设计
RB-tree有红黑二色,并且拥有左右子节点,要实现泛型容器,迭代器的设计是关键。要考虑迭代器的类型、前进、后退、引用、成员访问等操作。
RB-tree迭代器属于双向迭代器,不可随机访问,较为特殊的是前进和后退操作,RB-tree迭代器的前进操作operator++()调用_Rb_tree_increment(),RB-tree的后退操作operator–()调用_Rb_tree_decrement();前进或后退完全依据二叉搜索树的节点排列规则。

//迭代器前进后退操作
struct __rb_tree_base_iterator
{
  typedef __rb_tree_node_base::base_ptr base_ptr;
  typedef bidirectional_iteraotr_tag iterator_category;
  typedef ptrdiff_t difference_type;
  base_ptr node; //迭代器指向的节点
  void increment()
  {
    if(nood->right != 0) //如果有右子节点,找到右子节点的最左子节点
    {
      node = node->right; //向右走
      while (node->left != 0) //一直往左子树走到底
        node = node->left; //即是解答
    }
    else //如果没有右子节点,找到为左子节点的父节点
    {
      base_ptr y = node->parent; //令y为父节点
      while (node == y->right) //如果当前节点是个右子节点
      {
        node = y; //一直上溯,直到节点不为右子节点为止
        y = y->parent; //设置循环条件
      } //循环结束,为左子节点的父节点找到,即node->parent
      if (node->right != y) //正常情况下
        node = y; //父节点为寻找的节点
      //但在寻找根节点的下一节点,但根节点无右子节点时,node即为解答
    } //根节点与头节点互为父节点,根节点无右子节点时,父节点右子节点为根节点
  }

  void decrement()
  { //头节点为end(),头节点的右子节点即mostright,指向整棵树的max节点
    if (node->color == __rb_tree_red && node->parent->parent == node) //如果是红节点,且父节点的父节点等于自己,即头节点时
      node = node->right; //头节点的右节点即为解答
    else if (node->left != 0) //如果有左子节点,找到左子节点的最右子节点
    {
      base_ptr y = node->left; //令y为左子节点
      while (y->right != 0) //一直往右子树走到底
        y = y->right;
      node = y; //最后即为答案
    }
    else //无左子节点时,找到为右子节点的父节点即可
    {
      base_ptr y = node->parent; //令y为父节点
      while (node == y->left) //如果当前节点为左子节点
      {
        node = y; //一直上溯,直到节点不为左子节点为止
        y = y->parent;
      }
      node = y; //循环结束,父节点即为寻找的上一节点
    }
  }
};

树状结构的各种操作,需要注意边界情况,根节点需要有特殊处理,RB-tree在实现中设计头节点header,header与root互为对方父节点。
插入新节点时,不但要依照RB-tree的规则调整,还要维护header头节点的正确性,头节点的父节点指向根节点,左子节点指向最小节点,右子节点指向最大节点。

namespace std _GLIBCXX_VISIBILITY(default)
{

  enum _Rb_tree_color { _S_red = false, _S_black = true }; //颜色设置

  struct _Rb_tree_node_base //base节点结构设计,父节点,左右子树,节点颜色
  {
    typedef _Rb_tree_node_base* _Base_ptr; //指针类型
    typedef const _Rb_tree_node_base* _Const_Base_ptr; //const指针类型

    _Rb_tree_color	_M_color; //节点颜色,非红即黑
    _Base_ptr		_M_parent; //父节点
    _Base_ptr		_M_left; //左子节点
    _Base_ptr		_M_right; //右子节点
    //以下省略const版本
    static _Base_ptr //最小节点
    _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
    {
      while (__x->_M_left != 0) __x = __x->_M_left; //一直向左走即找到最小值,二叉搜索树的特性
      return __x;
    }

    static _Base_ptr //最大节点
    _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
    {
      while (__x->_M_right != 0) __x = __x->_M_right; //一直向右走即找到最大值,二叉搜索树的特性
      return __x;
    }
  }; //_Rb_tree_node_base

  template<typename _Key_compare> //节点键值比较函数模板设计
    struct _Rb_tree_key_compare //在比较函数上提供值初始化
    {
      _Key_compare		_M_key_compare;
      //以下省略构造函数
    }; //_Rb_tree_key_compare

  struct _Rb_tree_header //头节点设计
  { //头节点默认初始化及节点数管理
    _Rb_tree_node_base	_M_header; //头节点
    size_t		_M_node_count; //树的大小

    _Rb_tree_header() _GLIBCXX_NOEXCEPT //默认构造函数
    {
      _M_header._M_color = _S_red; //头节点颜色为红,区分header与root
      _M_reset(); //头节点初始化
    }

    _Rb_tree_header(_Rb_tree_header&& __x) noexcept //移动构造函数
    {
      if (__x._M_header._M_parent != nullptr) //头节点__x根节点不为空时
		_M_move_data(__x); //头节点赋值为__x头节点
      else //否则
	  {
	    _M_header._M_color = _S_red; //头节点颜色为红
	    _M_reset(); //置初始状态
	  }
    }

    void
    _M_move_data(_Rb_tree_header& __from) //赋值为__from头节点
    {
      _M_header._M_color = __from._M_header._M_color;
      _M_header._M_parent = __from._M_header._M_parent;
      _M_header._M_left = __from._M_header._M_left;
      _M_header._M_right = __from._M_header._M_right;
      _M_header._M_parent->_M_parent = &_M_header;
      _M_node_count = __from._M_node_count;

      __from._M_reset(); //__from头节点置空
    }

    void
    _M_reset() //头节点置初始状态
    {
      _M_header._M_parent = 0; //header的根节点为空
      _M_header._M_left = &_M_header; //header的左子节点为自己
      _M_header._M_right = &_M_header; //header的右子节点为自己
      _M_node_count = 0; //节点数为0
    }
  }; //_Rb_tree_header

  template<typename _Val> //节点结构设计,在_Rb_tree_node_base基础上增加节点值
    struct _Rb_tree_node : public _Rb_tree_node_base
    {
      typedef _Rb_tree_node<_Val>* _Link_type; //节点指针类型
      
      __gnu_cxx::__aligned_membuf<_Val> _M_storage; //节点值

      _Val*
      _M_valptr() //返回指向节点值的指针
      { return _M_storage._M_ptr(); }

      const _Val*
      _M_valptr() const //const版本
      { return _M_storage._M_ptr(); }
    }; //_Rb_tree_node
    
  //前进后退操作,省略const版本
  _GLIBCXX_PURE _Rb_tree_node_base* //前进操作,前面有详细代码设计
  _Rb_tree_increment(_Rb_tree_node_base* __x) throw ();
  _GLIBCXX_PURE _Rb_tree_node_base* //后退
  _Rb_tree_decrement(_Rb_tree_node_base* __x) throw ();

  template<typename _Tp>
    struct _Rb_tree_iterator //迭代器设计
    { //类型定义
      typedef _Tp  value_type; //数据类型
      typedef _Tp& reference; //左值引用类型
      typedef _Tp* pointer; //指针类型

      typedef bidirectional_iterator_tag iterator_category; //迭代器类型,双向迭代器
      typedef ptrdiff_t		  difference_type; //迭代器之间的距离

      typedef _Rb_tree_iterator<_Tp>	_Self;
      typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
      typedef _Rb_tree_node<_Tp>*	   _Link_type;

      _Rb_tree_iterator() _GLIBCXX_NOEXCEPT //默认构造函数
      : _M_node() { }
      explicit
      _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
      : _M_node(__x) { }
      //运算符重载
      reference //解引用运算符
      operator*() const _GLIBCXX_NOEXCEPT //获取节点值
      { return *static_cast<_Link_type>(_M_node)->_M_valptr(); }

      pointer //成员访问运算符
      operator->() const _GLIBCXX_NOEXCEPT
      { return static_cast<_Link_type> (_M_node)->_M_valptr(); }

      _Self& //前置递增运算符
      operator++() _GLIBCXX_NOEXCEPT
      {
		_M_node = _Rb_tree_increment(_M_node); 
		return *this;
      }

      _Self //后置递增运算符
      operator++(int) _GLIBCXX_NOEXCEPT
      {
		_Self __tmp = *this;
		_M_node = _Rb_tree_increment(_M_node);
		return __tmp;
      }

      _Self& //前置递减运算符
      operator--() _GLIBCXX_NOEXCEPT
      {
		_M_node = _Rb_tree_decrement(_M_node);
		return *this;
      }

      _Self //后置递减运算符
      operator--(int) _GLIBCXX_NOEXCEPT
      {
		_Self __tmp = *this;
		_M_node = _Rb_tree_decrement(_M_node);
		return __tmp;
      }

      bool //相等比较运算符
      operator==(const _Self& __x) const _GLIBCXX_NOEXCEPT
      { return _M_node == __x._M_node; } //使用节点相等运算符比较

      bool //不等运算符
      operator!=(const _Self& __x) const _GLIBCXX_NOEXCEPT
      { return _M_node != __x._M_node; } //使用节点不等运算符比较

      _Base_ptr _M_node; //base节点对象,与容器产生连结关系
  }; //_Rb_tree_iterator
  //省略const_iterator设计

  template<typename _Val> //迭代器相等比较运算符
    inline bool
    operator==(const _Rb_tree_iterator<_Val>& __x,
	       const _Rb_tree_const_iterator<_Val>& __y) _GLIBCXX_NOEXCEPT
    { return __x._M_node == __y._M_node; } //使用节点相等运算符比较

  template<typename _Val> //迭代器不等比较运算符
    inline bool
    operator!=(const _Rb_tree_iterator<_Val>& __x,
	       const _Rb_tree_const_iterator<_Val>& __y) _GLIBCXX_NOEXCEPT
    { return __x._M_node != __y._M_node; } //使用节点不等运算符比较

  void //树中插入节点并调整树平衡及颜色修改
  _Rb_tree_insert_and_rebalance(const bool __insert_left,
				_Rb_tree_node_base* __x,
				_Rb_tree_node_base* __p,
				_Rb_tree_node_base& __header) throw ();
  _Rb_tree_node_base* //树中删除节点并调整树平衡及颜色修改
  _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
			       _Rb_tree_node_base& __header) throw ();

  //_Rb_tree设计
  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc = allocator<_Val> > //_Compare为比较函数对象,比较节点值
    class _Rb_tree
    { 
      typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
	rebind<_Rb_tree_node<_Val> >::other _Node_allocator; //节点内存分配器,分配类型_Rb_tree_node<_Val>

      typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits; //节点内存分配器的属性

      static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
	  "comparison object must be invocable with two arguments of key type");

    protected: //类型定义
      typedef _Rb_tree_node_base* 		_Base_ptr;
      typedef const _Rb_tree_node_base* 	_Const_Base_ptr;
      typedef _Rb_tree_node<_Val>* 		_Link_type;
      typedef const _Rb_tree_node<_Val>*	_Const_Link_type;

    public: //类型定义
      typedef _Key 				key_type;
      typedef _Val 				value_type;
      typedef value_type* 			pointer;
      typedef const value_type* 		const_pointer;
      typedef value_type& 			reference;
      typedef const value_type& 		const_reference;
      typedef size_t 				size_type;
      typedef ptrdiff_t 			difference_type;
      typedef _Alloc 				allocator_type;

    protected:
      _Link_type
      _M_get_node() //内存分配
      { return _Alloc_traits::allocate(_M_get_Node_allocator(), 1); }

      void
      _M_put_node(_Link_type __p) _GLIBCXX_NOEXCEPT //内存释放
      { _Alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); }

      template<typename... _Args>
	void //对象构造
	_M_construct_node(_Link_type __node, _Args&&... __args)
	{
	  __try
	    {
	      ::new(__node) _Rb_tree_node<_Val>;
	      _Alloc_traits::construct(_M_get_Node_allocator(),
				       __node->_M_valptr(),
				       std::forward<_Args>(__args)...);
	    }
	  __catch(...)
	    {
	      __node->~_Rb_tree_node<_Val>();
	      _M_put_node(__node);
	      __throw_exception_again;
	    }
	}

      void
      _M_destroy_node(_Link_type __p) noexcept //对象析构
      {
		_Alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr()); 
		__p->~_Rb_tree_node<_Val>();
      }
      
      template<typename... _Args>
		_Link_type
		_M_create_node(_Args&&... __args) //内存分配及对象构造
		{
		  _Link_type __tmp = _M_get_node(); //内存分配
		  _M_construct_node(__tmp, std::forward<_Args>(__args)...); //构造内容
		  return __tmp;
		}

      void
      _M_drop_node(_Link_type __p) //对象析构及内存释放
      {
		_M_destroy_node(__p); //析构内容
		_M_put_node(__p); //释放内存
      }

      template<typename _NodeGen> //复制一个节点,包括值和颜色
		_Link_type
		_M_clone_node(_Const_Link_type __x, _NodeGen& __node_gen)
		{
		  _Link_type __tmp = __node_gen(*__x->_M_valptr());
		  __tmp->_M_color = __x->_M_color;
		  __tmp->_M_left = 0;
		  __tmp->_M_right = 0;
		  return __tmp;
		}

    protected:
      template<typename _Key_compare,
	       bool /* _Is_pod_comparator */ = __is_pod(_Key_compare)> 
	struct _Rb_tree_impl //节点操作封装,内存分配,键值比较,头节点
	: public _Node_allocator
	, public _Rb_tree_key_compare<_Key_compare>
	, public _Rb_tree_header
	{
	  typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare; //_Key_compare节点键值比较函数
	  //以下省略构造函数
	}; //_Rb_tree_impl

      _Rb_tree_impl<_Compare> _M_impl;

    protected:
      //以下省略const返回
      _Base_ptr&
      _M_root() _GLIBCXX_NOEXCEPT //header的父节点即为根节点,header和root互为对方的父节点
      { return this->_M_impl._M_header._M_parent; }

      _Base_ptr&
      _M_leftmost() _GLIBCXX_NOEXCEPT //header左子节点
      { return this->_M_impl._M_header._M_left; }

      _Base_ptr&
      _M_rightmost() _GLIBCXX_NOEXCEPT //header右子节点
      { return this->_M_impl._M_header._M_right; }

      _Link_type
      _M_begin() _GLIBCXX_NOEXCEPT //头节点的父节点为起始节点
      { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); }

      _Base_ptr //尾后节点为header节点
      _M_end() _GLIBCXX_NOEXCEPT
      { return &this->_M_impl._M_header; }

      static const_reference //节点__x的值
      _S_value(_Const_Link_type __x)
      { return *__x->_M_valptr(); }

      static const _Key& //节点__x的键值
      _S_key(_Const_Link_type __x)
      { return _KeyOfValue()(_S_value(__x)); }

      static _Link_type //节点__x左子节点
      _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT
      { return static_cast<_Link_type>(__x->_M_left); }

      static _Link_type //节点__x右子节点
      _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT
      { return static_cast<_Link_type>(__x->_M_right); }

      static const_reference
      _S_value(_Const_Base_ptr __x)
      { return *static_cast<_Const_Link_type>(__x)->_M_valptr(); }

      static const _Key&
      _S_key(_Const_Base_ptr __x)
      { return _KeyOfValue()(_S_value(__x)); }

      static _Base_ptr //树中最小值
      _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
      { return _Rb_tree_node_base::_S_minimum(__x); }

      static _Base_ptr //树中最大值
      _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT
      { return _Rb_tree_node_base::_S_maximum(__x); }

    public: //类型定义
      typedef _Rb_tree_iterator<value_type>       iterator; //迭代
      typedef _Rb_tree_const_iterator<value_type> const_iterator; //const迭代器
      typedef std::reverse_iterator<iterator>       reverse_iterator; //反向迭代器
      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

      pair<_Base_ptr, _Base_ptr> //元素插入,节点键值不允许重复
      _M_get_insert_unique_pos(const key_type& __k)
      {
        typedef pair<_Base_ptr, _Base_ptr> _Res;
        _Link_type __x = _M_begin(); //从根节点开始
        _Base_ptr __y = _M_end();
        bool __comp = true;
        while (__x != 0) //根节点往下,寻找合适插入点
		{ //循环只做了小于比较,不小于时即为等于或大于情况,需要再次比较
		  __y = __x;
		  __comp = _M_impl._M_key_compare(__k, _S_key(__x)); //__k键值与__x键值比较
		  __x = __comp ? _S_left(__x) : _S_right(__x); //__k键值较小时往左,大于或等于时往右
		} //while循环后,__y为插入点__x的父节点,__y必为叶节点
	    iterator __j = iterator(__y); //迭代器j指向插入点父节点
	    if (__comp) //上次比较为小于时,需区分全为小于和不全为小于情况
		{
		  if (__j == begin()) //当一路比较均为小于情况直到最小节点时
		    return _Res(__x, __y); //节点可直接插入
		  else //当一路比较不全为小于情况时,需要增加与上一个键值比较情况
		    --__j; //__k键值小于__j键值,需大于__j前一个键值才可插入
		} //迭代器++或--指向下一个大或上一个小的键值
	  //上次比较为大于或等于时,需增加比较去掉等于情况,及上次比较不全为小于需增加与上一个键值比较情况
        if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
		  return _Res(__x, __y); //当比较以上两种情况小于成立时,节点可直接插入
        return _Res(__j._M_node, 0); //否则节点不可插入
      }
      
      pair<_Base_ptr, _Base_ptr> //元素插入,节点键值允许重复
      _M_get_insert_equal_pos(const key_type& __k)
      {
        typedef pair<_Base_ptr, _Base_ptr> _Res;
        _Link_type __x = _M_begin(); //从根节点开始
        _Base_ptr __y = _M_end();
        while (__x != 0) //根节点往下,寻找合适插入点
		{
		  __y = __x;
		  __x = _M_impl._M_key_compare(__k, _S_key(__x)) ?
			_S_left(__x) : _S_right(__x);
		}
        return _Res(__x, __y);
      }
      
    private:
      template<typename _Arg, typename _NodeGen>
	  iterator
	  _M_insert_(_Base_ptr __x, _Base_ptr __p, _Arg&& __v, _NodeGen& __node_gen)
	  { //需另外处理__p为header,__v为左插入点__p为最左节点时
	    bool __insert_left = (__x != 0 || __p == _M_end() //__p为header时
				      || _M_impl._M_key_compare(_KeyOfValue()(__v),
								_S_key(__p))); //__v为左插入节点时
	
		_Link_type __z = __node_gen(_GLIBCXX_FORWARD(_Arg, __v)); //新增节点
	
		_Rb_tree_insert_and_rebalance(__insert_left, __z, __p,
					      this->_M_impl._M_header); //设定插入点颜色并调整树
		++_M_impl._M_node_count; //节点数累加
		return iterator(__z); //返回迭代器指向新增节点
      }
      
    public: 
      //构造函数与析构函数
      _Rb_tree() = default;

      _Rb_tree(const _Compare& __comp,
	       const allocator_type& __a = allocator_type())
      : _M_impl(__comp, _Node_allocator(__a)) { }

      _Rb_tree(const _Rb_tree& __x)
      : _M_impl(__x._M_impl) { }

      _Rb_tree(const allocator_type& __a)
      : _M_impl(_Compare(), _Node_allocator(__a))
      { }

      _Rb_tree(const _Rb_tree& __x, const allocator_type& __a)
      : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a))
      { }

      _Rb_tree(_Rb_tree&&) = default;

      _Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
      : _Rb_tree(std::move(__x), _Node_allocator(__a))
      { }

      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
      : _M_impl(__x._M_impl._M_key_compare, std::move(__a))
      { }

      ~_Rb_tree() _GLIBCXX_NOEXCEPT
      { _M_erase(_M_begin()); }

      _Rb_tree&
      operator=(const _Rb_tree& __x)
      {
        if (this != &__x)
		{
	  	  // Note that _Key may be a constant type.
	  	  if (_Alloc_traits::_S_propagate_on_copy_assign())
	      {
	        auto& __this_alloc = this->_M_get_Node_allocator();
	        auto& __that_alloc = __x._M_get_Node_allocator();
	        if (!_Alloc_traits::_S_always_equal()
		  	  && __this_alloc != __that_alloc)
			{
		  	  // Replacement allocator cannot free existing storage, we need
		  	  // to erase nodes first.
		  	  clear();
		  	  std::__alloc_on_copy(__this_alloc, __that_alloc);
		    }
	      }
	  	  _Reuse_or_alloc_node __roan(*this);
	      _M_impl._M_reset();
	      _M_impl._M_key_compare = __x._M_impl._M_key_compare;
	      if (__x._M_root() != 0)
	        _M_root() = _M_copy(__x, __roan);
	    }
        return *this;
      }

      _Compare
      key_comp() const
      { return _M_impl._M_key_compare; }
     
      //以下省略const返回
      iterator
      begin() _GLIBCXX_NOEXCEPT //树的起始节点为最左节点
      { return iterator(this->_M_impl._M_header._M_left); }

      iterator
      end() _GLIBCXX_NOEXCEPT //树的尾后节点为header节点
      { return iterator(&this->_M_impl._M_header); }

      reverse_iterator
      rbegin() _GLIBCXX_NOEXCEPT
      { return reverse_iterator(end()); }

      reverse_iterator
      rend() _GLIBCXX_NOEXCEPT
      { return reverse_iterator(begin()); }

      bool
      empty() const _GLIBCXX_NOEXCEPT //判断树是否为空
      { return _M_impl._M_node_count == 0; }

      size_type
      size() const _GLIBCXX_NOEXCEPT //树的节点数
      { return _M_impl._M_node_count; }

      size_type
      max_size() const _GLIBCXX_NOEXCEPT
      { return _Alloc_traits::max_size(_M_get_Node_allocator()); }

      void
      swap(_Rb_tree& __t) { }

    public: 
      iterator
      erase(const_iterator __position) { }

      iterator
      erase(iterator __position) { }
      
      size_type
      erase(const key_type& __x) { }

      iterator
      erase(const_iterator __first, const_iterator __last) { }

      void
      erase(const key_type* __first, const key_type* __last)
      {
        while (__first != __last)
	      erase(*__first++);
      }

      void
      clear() _GLIBCXX_NOEXCEPT
      {
		_M_erase(_M_begin());
		_M_impl._M_reset();
      }
      //find、lower_bound、upper_bound、equal_range,以下省略const返回
      iterator
      find(const key_type& __k) { }

      size_type
      count(const key_type& __k) const { }

      iterator
      lower_bound(const key_type& __k) { }

      iterator
      upper_bound(const key_type& __k) { }

      pair<iterator, iterator>
      equal_range(const key_type& __k) { }

      _Rb_tree&
      operator=(_Rb_tree&&) { }
      
      //以下省略部分内容
    }; //_Rb_tree

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline bool
    operator==(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	       const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    {
      return __x.size() == __y.size()
	     && std::equal(__x.begin(), __x.end(), __y.begin());
    }

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline bool
    operator<(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	      const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    {
      return std::lexicographical_compare(__x.begin(), __x.end(), 
					  __y.begin(), __y.end());
    }

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline bool
    operator!=(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	       const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    { return !(__x == __y); }

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline bool
    operator>(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	      const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    { return __y < __x; }

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline bool
    operator<=(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	       const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    { return !(__y < __x); }

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline bool
    operator>=(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	       const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    { return !(__x < __y); }

  template<typename _Key, typename _Val, typename _KeyOfValue,
	   typename _Compare, typename _Alloc>
    inline void
    swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
	 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y)
    { __x.swap(__y); }

} // namespace
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值