STL之list(一)

       list概述

       相对于vector的连续性空间,list就显的复杂许多,它的好处是每次安插或删除一个元素,就配置或释放一个元素空间。因此,list对于空间的运用有绝对的精确,一点也不浪费。而且,对于任何职位的元素安插或元素移除,list永远是常数时间。

       list和vector是两个最常使用的容器。什么时机下最合适使用哪一种容器,必须视元素的多寡,元素的构造复杂度,元素存取行为的特性而定。

       list的节点

       list本身和list的节点是不同的结构,需要分开设计,以下是STL list的节点node结构:   

template <class T>
struct __list_node
{
  typedef void* void_pointer;
  void_pointer next;
  void_pointer prev;
  T data;
};

      list的迭代器

      list不在能够像vector一样以原生指标作为迭代器,因为其节点不保证在存储空间中连续存在。list迭代器必须有能力指向list的节点,并有能力做正确的递增,递减,取值,成员存取...等动作。STL list是一个双向串行,迭代器必须具备迁移,后移的能力。所以list提供的是Bidirectional Iterators。

      list有一个重要性质:安插动作(insert)和接合动作(splice)都不会造成原有的list迭代器失效。这在vector是不成立的,因为vector的安插动作可能造成记忆体重新配置,导致原有迭代器全部失效。甚至list的元素删除动作erase,也只有(指向被删除元素)的那个迭代器失效,其它迭代器不受影响。      

// 至于为什么不使用默认参数, 这个是因为有一些编译器不能提供推导能力,
// 而作者又不想维护两份代码, 故不使用默认参数
template<class T, class Ref, class Ptr>
struct __list_iterator
{
  // 标记为'STL标准强制要求'的typedefs用于提供iterator_traits<I>支持
  typedef __list_iterator<T, T&, T*>             iterator;   // STL标准强制要求
  typedef __list_iterator<T, const T&, const T*> const_iterator;
  typedef __list_iterator<T, Ref, Ptr>           self;

  typedef bidirectional_iterator_tag iterator_category;
  typedef T value_type;                                 // STL标准强制要求
  typedef Ptr pointer;                                  // STL标准强制要求
  typedef Ref reference;                                // STL标准强制要求
  typedef __list_node<T>* link_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;                    // STL标准强制要求

  // 这个是迭代器实际管理的资源指针
  link_type node;

  __list_iterator(link_type x) : node(x) {}
  __list_iterator() {}
  __list_iterator(const iterator& x) : node(x.node) {}

  // 在STL算法中需要迭代器提供支持
  bool operator==(const self& x) const { return node == x.node; }
  bool operator!=(const self& x) const { return node != x.node; }

  // 重载operator *, 返回实际维护的数据
  reference operator*() const { return (*node).data; }

#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */

  // 前缀自加
  self& operator++()
  {
    node = (link_type)((*node).next);
    return *this;
  }

  // 后缀自加, 需要先产生自身的一个副本, 然会再对自身操作, 最后返回副本
  self operator++(int)
  {
    self tmp = *this;
    ++*this;
    return tmp;
  }

  self& operator--()
  {
    node = (link_type)((*node).prev);
    return *this;
  }

  self operator--(int)
  {
    self tmp = *this;
    --*this;
    return tmp;
  }
};

         list的数据结构

        list不仅是一个双向串行,而且还是一个环状双向串行。所以它只需要一个指标,便可以完成表现整个串行。如果让指标node指向可以置于尾端的一个空白节点,node便能符合STL对于[前闭后开]区间的要求,成为last迭代器,如下图所示:




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值