STL源码阅读(三)

STL源码阅读(三) (SGI STL v3.3)

stl_list.h (<list>)

// list结点基类
struct _List_node_base {
  _List_node_base* _M_next; // 指向下一个结点
  _List_node_base* _M_prev; // 指向前一个结点
};

// list结点
template <class _Tp>
struct _List_node : public _List_node_base {
  _Tp _M_data;  // 每个结点上的数据
};

// list迭代器,迭代器类型双向迭代器
struct _List_iterator_base;
template<class _Tp, class _Ref, class _Ptr>
struct _List_iterator : public _List_iterator_base;

// _M_node指向list结点,每次迭代更新迭代器的_M_node的指向
_List_node_base* _M_node;   // 指向list结点

// list内存分配
// 该类中保存了内存分配器_Node_allocator与所分配的_List_node结点内存的指针_M_node
template <class _Tp, class _Allocator, bool _IsStatic>
class _List_alloc_base;
// _List_alloc_base的特化版本,不需保存内存分配器(使用静态的分配器),只有一个数据成员_M_node
template <class _Tp, class _Allocator>
class _List_alloc_base<_Tp, _Allocator, true>;

// list基类
template <class _Tp, class _Alloc>
class _List_base 
  : public _List_alloc_base<_Tp, _Alloc,
                            _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
{
public:
  typedef _List_alloc_base<_Tp, _Alloc,
                           _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
          _Base; 
  typedef typename _Base::allocator_type allocator_type;

  _List_base(const allocator_type& __a) : _Base(__a) {
    _M_node = _M_get_node();        // 获得一个新结点
    _M_node->_M_next = _M_node;     // list是一个双向环向状量表,哨兵结点
    _M_node->_M_prev = _M_node;
  }
  ~_List_base() {
    clear();    // 清除链表中的所有元素
    _M_put_node(_M_node);  // 由此可见list有一个哨兵结点,不存数据,指向整个链表
  }

  void clear();
};

// 清除量表中的所有元素   
template <class _Tp, class _Alloc>
void _List_base<_Tp,_Alloc>::clear() 
{
  _List_node<_Tp>* __cur = (_List_node<_Tp>*) _M_node->_M_next;
  while (__cur != _M_node) {
    _List_node<_Tp>* __tmp = __cur;
    __cur = (_List_node<_Tp>*) __cur->_M_next;
    _Destroy(&__tmp->_M_data);
    _M_put_node(__tmp);
  }
  _M_node->_M_next = _M_node;
  _M_node->_M_prev = _M_node;
}

template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class list : protected _List_base<_Tp, _Alloc>;

// list中_M_node是指向哨兵结点的
iterator begin()             { return (_Node*)(_M_node->_M_next); }

// 注意swap只是交换哨兵结点的指针
void swap(list<_Tp, _Alloc>& __x) { __STD::swap(_M_node, __x._M_node); }

// 将[__first, __last)中的元素移到__position之前,splice的实现
void transfer(iterator __position, iterator __first, iterator __last) {
    if (__position != __last) {
      // Remove [first, last) from its old position.
      __last._M_node->_M_prev->_M_next     = __position._M_node;
      __first._M_node->_M_prev->_M_next    = __last._M_node;
      __position._M_node->_M_prev->_M_next = __first._M_node; 

      // Splice [first, last) into its new position.
      _List_node_base* __tmp      = __position._M_node->_M_prev;
      __position._M_node->_M_prev = __last._M_node->_M_prev;
      __last._M_node->_M_prev     = __first._M_node->_M_prev; 
      __first._M_node->_M_prev    = __tmp;
    }
}

// 注意,unique是移除连续相等的元素
template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::unique()
{
  iterator __first = begin();
  iterator __last = end();
  if (__first == __last) return;
  iterator __next = __first;
  while (++__next != __last) {
    if (*__first == *__next)
      erase(__next);
    else
      __first = __next;
    __next = __first;
  }
}

// merge两个已排序的list,按升序
template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::merge(list<_Tp, _Alloc>& __x)
{
  iterator __first1 = begin();
  iterator __last1 = end();
  iterator __first2 = __x.begin();
  iterator __last2 = __x.end();
  while (__first1 != __last1 && __first2 != __last2)
    if (*__first2 < *__first1) {
      iterator __next = __first2;
      transfer(__first1, __first2, ++__next);
      __first2 = __next;
    }
    else
      ++__first1;
  if (__first2 != __last2) transfer(__last1, __first2, __last2);
}


// 没弄懂reverse的实现
inline void __List_base_reverse(_List_node_base* __p)
{
  _List_node_base* __tmp = __p;
  do {
    __STD::swap(__tmp->_M_next, __tmp->_M_prev);
    __tmp = __tmp->_M_prev;     // Old next node is now prev.
  } while (__tmp != __p);
}

template <class _Tp, class _Alloc>
inline void list<_Tp, _Alloc>::reverse() 
{
  __List_base_reverse(this->_M_node);
}    

// 归并算法实现list sort排序,保持相等元素的相对顺序
template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::sort()
{
  // Do nothing if the list has length 0 or 1.
  if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) {
    list<_Tp, _Alloc> __carry;
    list<_Tp, _Alloc> __counter[64];    // 模拟递归实现
    int __fill = 0;
    while (!empty()) {
      __carry.splice(__carry.begin(), *this, begin());
      int __i = 0;
      while(__i < __fill && !__counter[__i].empty()) {
        __counter[__i].merge(__carry);
        __carry.swap(__counter[__i++]);
      }
      __carry.swap(__counter[__i]);         
      if (__i == __fill) ++__fill;
    } 

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

参考资料

  1. sgi STL
  2. cppreference.com

转载于:https://www.cnblogs.com/corfox/p/6063306.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值