STL学习——Slist篇

来源:互联网 发布:java线上培训班 编辑:程序博客网 时间:2024/05/16 05:32

STL学习——Slist篇

  • 简介

    STL中List是双向链表,而Slist是单向链表。它们的区别:Slist的迭代器是单向的Forward Iterator,而list的迭代器是双向的Bidirectional Iterator。Slist所耗用的空间更小,操作更快。它们共同的特点是,插入、移除、接合等操作并不会造成原有的迭代器失效。slist插入时,需要从前遍历,找到插入点的位置。为了更快插入,提供了insert_after,erase_after。slist提供push_front()操作,故其元素次序与元素插入顺序相反。

  • 节点与操作

    slist节点和迭代器设计上,使用了继承关系,故较复杂。下面是其节点信息。

    // 单向链表的节点基本结构struct _Slist_node_base{  _Slist_node_base* _M_next;};  // 单向链表的节点结构template <class _Tp>struct _Slist_node : public _Slist_node_base{  _Tp _M_data;};// 全局函数:已知某一节点,插入新节点于其后inline _Slist_node_base*__slist_make_link(_Slist_node_base* __prev_node,                  _Slist_node_base* __new_node){  __new_node->_M_next = __prev_node->_M_next;    // 令new节点的下一节点为prev节点的下一节点  __prev_node->_M_next = __new_node;  return __new_node;}// 查找node节点的前一个节点inline _Slist_node_base* __slist_previous(_Slist_node_base* __head,                 const _Slist_node_base* __node){  while (__head && __head->_M_next != __node)    // 从头遍历,查找node的前一个节点    __head = __head->_M_next;  return __head;}// 查找node节点的前一个节点inline const _Slist_node_base* __slist_previous(const _Slist_node_base* __head,                 const _Slist_node_base* __node){  while (__head && __head->_M_next != __node)    // 从头遍历,查找node的前一个节点    __head = __head->_M_next;  return __head;}// 将before_first与before_after之间的节点插入到pos后面inline void __slist_splice_after(_Slist_node_base* __pos,                                 _Slist_node_base* __before_first,                                 _Slist_node_base* __before_last){  if (__pos != __before_first && __pos != __before_last) {    // 记录before_first的next节点    _Slist_node_base* __first = __before_first->_M_next;    // 记录pos的next节点    _Slist_node_base* __after = __pos->_M_next;    // 先将befor_first与before_last前后挂接在一起    __before_first->_M_next = __before_last->_M_next;    // 将before_first的下一个节点挂接在pos的后面    __pos->_M_next = __first;    // 将before_last的next与pos_next进行挂接     __before_last->_M_next = __after;  }}// 链表的翻转操作inline _Slist_node_base* __slist_reverse(_Slist_node_base* __node){  _Slist_node_base* __result = __node;  __node = __node->_M_next;  __result->_M_next = 0;  while(__node) {    _Slist_node_base* __next = __node->_M_next;    // 记住下一个节点    __node->_M_next = __result;     // 将当前节点插入到result节点的最前    __result = __node;              // 更新result节点    __node = __next;                // 更新node节点  }  return __result;                  // 返回逆转的链表}// 全局函数:单向链表的大小(元素个数)inline size_t __slist_size(_Slist_node_base* __node){  size_t __result = 0;  for ( ; __node != 0; __node = __node->_M_next)    ++__result;  return __result;}// 单向链表的迭代器基本结构struct _Slist_iterator_base{  typedef size_t               size_type;  typedef ptrdiff_t            difference_type;  typedef forward_iterator_tag iterator_category;     // 注意,单向  _Slist_node_base* _M_node;                          // 指向节点基本结构  _Slist_iterator_base(_Slist_node_base* __x) : _M_node(__x) {}  void _M_incr() { _M_node = _M_node->_M_next; }      // 前进一个节点  bool operator==(const _Slist_iterator_base& __x) const {   // 判断链表是否相等    return _M_node == __x._M_node;  }  bool operator!=(const _Slist_iterator_base& __x) const {   // 判断链表是否不相等    return _M_node != __x._M_node;  }};// 单向链表的迭代器结构template <class _Tp, class _Ref, class _Ptr>struct _Slist_iterator : public _Slist_iterator_base{  typedef _Slist_iterator<_Tp, _Tp&, _Tp*>             iterator;  typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;  typedef _Slist_iterator<_Tp, _Ref, _Ptr>             _Self;  typedef _Tp              value_type;  typedef _Ptr             pointer;  typedef _Ref             reference;  typedef _Slist_node<_Tp> _Node;  _Slist_iterator(_Node* __x) : _Slist_iterator_base(__x) {}  // 调用slist<T>::end()时会造成__slist_iterator(0),于是调用上述函数  _Slist_iterator() : _Slist_iterator_base(0) {}     // 产生一个暂时对象,引发ctor  _Slist_iterator(const iterator& __x) : _Slist_iterator_base(__x._M_node) {}  reference operator*() const { return ((_Node*) _M_node)->_M_data; }#ifndef __SGI_STL_NO_ARROW_OPERATOR  pointer operator->() const { return &(operator*()); }#endif /* __SGI_STL_NO_ARROW_OPERATOR */  _Self& operator++()  {    _M_incr();     // 前进一个节点    return *this;  }  _Self operator++(int)  {    _Self __tmp = *this;    _M_incr();     // 前进一个节点    return __tmp;  }  // 注意没有实现operator--,因为这是一个forward iterator};template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >class slist : private _Slist_base<_Tp,_Alloc>{  __STL_CLASS_REQUIRES(_Tp, _Assignable);private:  typedef _Slist_base<_Tp,_Alloc> _Base;public:  typedef _Tp                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 _Slist_iterator<_Tp, _Tp&, _Tp*>             iterator;  typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;  typedef typename _Base::allocator_type allocator_type;  allocator_type get_allocator() const { return _Base::get_allocator(); }private:  typedef _Slist_node<_Tp>      _Node;  typedef _Slist_node_base      _Node_base;  typedef _Slist_iterator_base  _Iterator_base;  _Node* _M_create_node(const value_type& __x) {    _Node* __node = this->_M_get_node();    // 配置空间    __STL_TRY {      construct(&__node->_M_data, __x);     // 构造元素      __node->_M_next = 0;    }    __STL_UNWIND(this->_M_put_node(__node));    return __node;  }public:  explicit slist(const allocator_type& __a = allocator_type()) : _Base(__a) {}  slist(size_type __n, const value_type& __x,        const allocator_type& __a =  allocator_type()) : _Base(__a)    { _M_insert_after_fill(&this->_M_head, __n, __x); }  explicit slist(size_type __n) : _Base(allocator_type())    { _M_insert_after_fill(&this->_M_head, __n, value_type()); }#ifdef __STL_MEMBER_TEMPLATES  // We don't need any dispatching tricks here, because _M_insert_after_range  // already does them.  template <class _InputIterator>  slist(_InputIterator __first, _InputIterator __last,        const allocator_type& __a =  allocator_type()) : _Base(__a)    { _M_insert_after_range(&this->_M_head, __first, __last); }#else /* __STL_MEMBER_TEMPLATES */  slist(const_iterator __first, const_iterator __last,        const allocator_type& __a =  allocator_type()) : _Base(__a)    { _M_insert_after_range(&this->_M_head, __first, __last); }  slist(const value_type* __first, const value_type* __last,        const allocator_type& __a =  allocator_type()) : _Base(__a)    { _M_insert_after_range(&this->_M_head, __first, __last); }#endif /* __STL_MEMBER_TEMPLATES */  slist(const slist& __x) : _Base(__x.get_allocator())    { _M_insert_after_range(&this->_M_head, __x.begin(), __x.end()); }  slist& operator= (const slist& __x);  ~slist() {}  ...  // 两个slist互换:只要将head交换互指即可。  void swap(slist& __x)    { __STD::swap(this->_M_head._M_next, __x._M_head._M_next); }public:  reference front() { return ((_Node*) this->_M_head._M_next)->_M_data; }  const_reference front() const     { return ((_Node*) this->_M_head._M_next)->_M_data; }  // 从头部插入元素(新元素成为slist的第一个元素)  void push_front(const value_type& __x)   {    __slist_make_link(&this->_M_head, _M_create_node(__x));  }  void push_front() { __slist_make_link(&this->_M_head, _M_create_node()); }  // 注意:没有push_back()  // 从头部取走元素(删除之)。修改head  void pop_front() {    _Node* __node = (_Node*) this->_M_head._M_next;    this->_M_head._M_next = __node->_M_next;    destroy(&__node->_M_data);    this->_M_put_node(__node);  }
  • 参考文献

    STL源码剖析——侯捷

    STL源码

0 0
原创粉丝点击