STL 的 slist 分析(五)

#-slist #-STL

remove_if 允许用户自定义判断函数(或者是函数对象,需重载 operator()) 。来删除 slit 中值满足 __pred 条件的节点。

template <class _Tp, class _Alloc> 
template <class _Predicate>
void slist<_Tp,_Alloc>::remove_if(_Predicate __pred)
{
  _Node_base* __cur = &this->_M_head;
  while (__cur->_M_next) {
    if (__pred(((_Node*) __cur->_M_next)->_M_data))
      this->_M_erase_after(__cur);
    else
      __cur = __cur->_M_next;
  }
}

unique 允许自定义二元比较函数(或者是函数对象,需重载 operator()) 来删除 slist 中的重复节点,前提是 slist 是已排序的。

template <class _Tp, class _Alloc> template <class _BinaryPredicate> 
void slist<_Tp,_Alloc>::unique(_BinaryPredicate __pred)
{
  _Node* __cur = (_Node*) this->_M_head._M_next;
  if (__cur) {
    while (__cur->_M_next) {
      if (__pred(((_Node*)__cur)->_M_data, 
		 ((_Node*)(__cur->_M_next))->_M_data))
	this->_M_erase_after(__cur);
      else
	__cur = (_Node*) __cur->_M_next;
    }
  }
}

merge 允许提供自定义的大小比较函数,来实现两个有序链表的合并。

template <class _Tp, class _Alloc> template <class _StrictWeakOrdering>
void slist<_Tp,_Alloc>::merge(slist<_Tp,_Alloc>& __x,
			      _StrictWeakOrdering __comp)
{
  _Node_base* __n1 = &this->_M_head;
  while (__n1->_M_next && __x._M_head._M_next) {
    if (__comp(((_Node*) __x._M_head._M_next)->_M_data,
	       ((_Node*)       __n1->_M_next)->_M_data))
      __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next);
    __n1 = __n1->_M_next;
  }
  if (__x._M_head._M_next) {
    __n1->_M_next = __x._M_head._M_next;
    __x._M_head._M_next = 0;
  }
}

sort 函数允许提供自定义的大小比较函数来实现 slist 的排序。

template <class _Tp, class _Alloc> template <class _StrictWeakOrdering> 
void slist<_Tp,_Alloc>::sort(_StrictWeakOrdering __comp)
{
  if (this->_M_head._M_next && this->_M_head._M_next->_M_next) {
    slist __carry;
    slist __counter[64];
    int __fill = 0;
    while (!empty()) {
      __slist_splice_after(&__carry._M_head,
			   &this->_M_head, this->_M_head._M_next);
      int __i = 0;
      while (__i < __fill && !__counter[__i].empty()) {
	__counter[__i].merge(__carry, __comp);
	__carry.swap(__counter[__i]);
	++__i;
      }
      __carry.swap(__counter[__i]);
      if (__i == __fill)
	++__fill;
    }

    for (int __i = 1; __i < __fill; ++__i)
      __counter[__i].merge(__counter[__i-1], __comp);
    this->swap(__counter[__fill-1]);
  }
}

operator= 用来将链表 __x 中的内容复制到当前 slist 中。并且覆盖掉原先 __slist 的内容。

template <class _Tp, class _Alloc>
slist<_Tp,_Alloc>& slist<_Tp,_Alloc>::operator=(const slist<_Tp,_Alloc>& __x)
{
  if (&__x != this) {
    _Node_base* __p1 = &this->_M_head;
    _Node* __n1 = (_Node*) this->_M_head._M_next;
    const _Node* __n2 = (const _Node*) __x._M_head._M_next;
    while (__n1 && __n2) {
      __n1->_M_data = __n2->_M_data;
      __p1 = __n1;
      __n1 = (_Node*) __n1->_M_next;
      __n2 = (const _Node*) __n2->_M_next;
    }
    if (__n2 == 0)
      this->_M_erase_after(__p1, 0);
    else
      _M_insert_after_range(__p1, const_iterator((_Node*)__n2), 
				  const_iterator(0));
  }
  return *this;
}

_M_fill_assign 函数用来将 __n 个值为 __val 的节点复制到当前 slist 中并且覆盖点 slist 中原先的内容。

template <class _Tp, class _Alloc>
void slist<_Tp, _Alloc>::_M_fill_assign(size_type __n, const _Tp& __val) {
  _Node_base* __prev = &this->_M_head;
  _Node* __node = (_Node*) this->_M_head._M_next;
  for ( ; __node != 0 && __n > 0 ; --__n) {
    __node->_M_data = __val;
    __prev = __node;
    __node = (_Node*) __node->_M_next;
  }
  if (__n > 0)
    _M_insert_after_fill(__prev, __n, __val);
  else
    this->_M_erase_after(__prev, 0);
}

assign 函数用来将 __n 个值为 __val 的节点复制到当前 slist 中,并且覆盖掉原先 slist 中的内容,通过调用 _M_fill_assign 来实现。

  void assign(size_type __n, const _Tp& __val)
    { _M_fill_assign(__n, __val); }

assign 函数,根据模板形参类型的不同,分别调用 _M_assign_dispatch 的两种不同定义。如果模板形参类型为整型则调用第一种定义,否则调用第二种定义。通过用 _InputIterator 来实例化 _Is_Integer 可以检测出 _InputIterator 是否为整型。如果 _InputIterator 为整型,则 _Integral 为 _true_type 的类型别名,否则为 _false_type 的类型别名。

  template <class _InputIterator>
  void assign(_InputIterator __first, _InputIterator __last) {
    typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
    _M_assign_dispatch(__first, __last, _Integral());
  }

函数 _M_assign_dispatch 调用 _M_fill_assign 函数将 __n 个值为 __val 的节点复制到当前 slist。替换掉 slist 原先的节点。

  template <class _Integer>
  void _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
    { _M_fill_assign((size_type) __n, (_Tp) __val); }

函数 _M_assign_dispatch 用 __first 和 __last 之间的元素构造一个新节点,并将这些新节点复制到当前 slist 。替换掉 slist 原先的节点。

template <class _Tp, class _Alloc> template <class _InputIter>
void
slist<_Tp, _Alloc>::_M_assign_dispatch(_InputIter __first, _InputIter __last,
				       __false_type)
{
  _Node_base* __prev = &this->_M_head;
  _Node* __node = (_Node*) this->_M_head._M_next;
  while (__node != 0 && __first != __last) {
    __node->_M_data = *__first;
    __prev = __node;
    __node = (_Node*) __node->_M_next;
    ++__first;
  }
  if (__first != __last)
    _M_insert_after_range(__prev, __first, __last);
  else
    this->_M_erase_after(__prev, 0);
}

operator== 判断两个链表是否相等,判断相等的要求有两点,第一,两个链表的节点个数要一致;第二,两个链表的对应位置的节点的值要相等。

template <class _Tp, class _Alloc>
inline bool 
operator==(const slist<_Tp,_Alloc>& _SL1, const slist<_Tp,_Alloc>& _SL2)
{
  typedef typename slist<_Tp,_Alloc>::const_iterator const_iterator;
  const_iterator __end1 = _SL1.end();
  const_iterator __end2 = _SL2.end();

  const_iterator __i1 = _SL1.begin();
  const_iterator __i2 = _SL2.begin();
  while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) {
    ++__i1;
    ++__i2;
  }
  return __i1 == __end1 && __i2 == __end2;
}

operator< 用来比较两个 slist 的大小关系。具体的判断方法通过调用 lexicographical_compare 来对 slist 中的元素按字典序来进行比较。lexicographical_compare 在 stl_algobase.h 中定义。

template <class _Tp, class _Alloc>
inline bool
operator<(const slist<_Tp,_Alloc>& _SL1, const slist<_Tp,_Alloc>& _SL2)
{
  return lexicographical_compare(_SL1.begin(), _SL1.end(), 
				 _SL2.begin(), _SL2.end());
}

STL 的 slist 分析(一)</br> STL 的 slist 分析(二)</br> STL 的 slist 分析(三)</br> STL 的 slist 分析(四)</br> STL 的 slist 分析(五)</br>