现在的位置: 首页 > 综合 > 正文

STL源码剖析 – 第4章 序列式容器 – ilist

2019年07月18日 ⁄ 综合 ⁄ 共 3237字 ⁄ 字号 评论关闭

4.9.1 slist概述

    在STL标准中提供了双向链表list,本文介绍的是SGISTL中<stl_slist.h>定义的单向链表slist。单向链表的迭代器是属于正向迭代器,所以在单链表进行插入元素时,在指定节点之后插入时时间是常数O(1),在指定节点之前插入时需要线性时间O(n)。相比于双向链表list,它所耗用的空间更小,某些操作更快。slist和list有一个共同的特殊是:它们的插入,移除,拼接等操作不会造成原有的迭代器失效。

    根据STL的习惯,插入操作会将新元素插入于指定位置之前,作为单向链表,slist不能回头定出前一个位置,因此它必须从头找起。为此,slist特别提供了insert_after() 和erase_after()供灵活使用。同理,slist只提供push_front()。

4.9.2 slist的节点

        slist的节点结构只有存储节点数据和指向下一个节点的指针。

//单向链表的节点基本结构  
struct _Slist_node_base  
{  
  _Slist_node_base* _M_next;  
};  
//单向链表节点结构  
template <class _Tp>  
struct _Slist_node : public _Slist_node_base  
{  
  _Tp _M_data;  
};  

4.9.3 slist的迭代器

    由于slist是单向链表,所以只提供正向迭代器,若要查找指定节点的前一个节点时,operator--不能使用,只能从头遍历,但是可以operator++和operator*操作;

//单向链表的迭代器的基本结构  
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_iterator() : _Slist_iterator_base(0) {}  
  _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 */  
  
  //前缀operator++  
  _Self& operator++()  
  {  
    _M_incr();  
    return *this;  
  }  
  //后缀operator++  
  _Self operator++(int)  
  {  
    _Self __tmp = *this;  
    _M_incr();  
    return __tmp;  
  }  
  //单向链表不能operator--操作  
};  

4.9.4 slist的数据结构

      slist单向链表只需要给出该链表的头部head,便可以通过head->next遍历该链表;

 typedef simple_alloc<_Slist_node<_Tp>, _Alloc> _Alloc_type;  
  _Slist_node<_Tp>* _M_get_node() { return _Alloc_type::allocate(1); }  
  void _M_put_node(_Slist_node<_Tp>* __p) { _Alloc_type::deallocate(__p, 1); }  
  
  _Slist_node_base* _M_erase_after(_Slist_node_base* __pos)  
  {  
    _Slist_node<_Tp>* __next = (_Slist_node<_Tp>*) (__pos->_M_next);  
    _Slist_node_base* __next_next = __next->_M_next;  
    __pos->_M_next = __next_next;  
    destroy(&__next->_M_data);  
    _M_put_node(__next);  
    return __next_next;  
  }  
  _Slist_node_base* _M_erase_after(_Slist_node_base*, _Slist_node_base*);  
  
protected:  
  _Slist_node_base _M_head;  
};    
  
  
//单向链表slist定义  
template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >  
class slist : private _Slist_base<_Tp,_Alloc>  
{  
  // requirements:  
  
  __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;  
  
  
private:  
  typedef _Slist_node<_Tp>      _Node;  
  typedef _Slist_node_base      _Node_base;  
  typedef _Slist_iterator_base  _Iterator_base;  
  ...  
};  

 

抱歉!评论已关闭.