STL list

list的节点结构:
template <class T>
struct __list_node {
  typedef void* void_pointer;
  void_pointer next;
  void_pointer prev;
  T data;
};

List不能像vector那样以普通的指针作为iterator,因为节点不能保证内存在空间上是连续的。
List是一个双向链表,所以需要有前移后移的功能,所以list提供的Bidirectional_iterator迭代器。
list的最重要性质就是insert操作和接合操作(splice)都不会造成list迭代器失效,这在vector上是不成立的。list的删除只会导致指向被删除元素的那个迭代器失效,其他迭代器不会失效。
// list的迭代器设计
template<class T, class Ref, class Ptr>
struct __list_iterator {
  typedef __list_iterator<T, T&, T*> iterator;
  typedef __list_iterator<T, const T&, const T*> const_iterator;
  typedef __list_iterator<T, Ref, Ptr> self;
  typedef bidirectional_iterator_tag iterator_category; // Bidirectional_iterator型别迭代器
  typedef T value_type;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef __list_node<T>* link_type;  // iterator内部的link类型是指针类型  
  typedef size_t size_type; 
  typedef ptrdiff_t difference_type;
  link_type node;   // 迭代器内部指向node的指针
  __list_iterator(link_type x) : node(x) {}
  __list_iterator() {}
  __list_iterator(const iterator& x) : node(x.node) {}
  bool operator==(const self& x) const { return node == x.node; }
  bool operator!=(const self& x) const { return node != x.node; }
// 一下对迭代器取值,取得是节点的data
  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;
  }
};

template <class T, class Alloc = alloc>  // 和vector一样默认使用alloc作为内存配置器
class list {
protected:
  typedef __list_node<T> list_node;
  typedef list_node* link_type;
...
protected:
  link_type node; // 只要一个指针就表示了整个环状的双向链表
};

整个list的示意图,只要刻意在环状链表的尾端加上一个空白节点,变符合stl规范的“前闭后开”[first, last )区间的规范,
这样几个函数变很容易的实现了
iterator begin() { return (link_type)((*node).next); }
iterator end() { return node; }
bool empty() const { return node->next == node; }
size_type size() const {
    size_type result = 0;
    distance(begin(), end(), result);
    return result;
 }
//取得是节点的内容(元素值)list_iterator中operator*()取得是节点的data
 reference front() { return *begin(); }
 //注意iterator是前开后闭区间,所有是*--end()是最后一个元素的内容
  reference back() { return *(--end()); }

对以list的结构有很清晰了解之后,相信对于list的使用就很简单了
另外补充一点:
 // list内部(非公开接口)提供了迁移操作,将某些连续范围[first, last)的元素迁移到某个特定位置position之前,技术上也很简单就是指针的移动
// 其他很多复杂的操作如splice(接合,将连续范围的元素从一个list移动到另外一个list的某个点),sort,merge, reverse等等操作都是在这个基础上实现
// STL算法sort只接受RamdonAccessIterator,所以list实现了一个自己sort member function.采用的是quick sort
  void transfer(iterator position, iterator first, iterator last) {
    if (position != last) {
      (*(link_type((*last.node).prev))).next = position.node;
      (*(link_type((*first.node).prev))).next = last.node;
      (*(link_type((*position.node).prev))).next = first.node;
      link_type tmp = link_type((*position.node).prev);
      (*position.node).prev = (*last.node).prev;
      (*last.node).prev = (*first.node).prev;
      (*first.node).prev = tmp;
    }
  }

// 逆向重置reverse,使用transfer很简单的实现了o(n)
// 其算法核心是历遍链表, 每次取出一个结点, 并插入到链表起始点  
// 历遍完成后链表满足倒置
template <class T, class Alloc>
void list<T, Alloc>::reverse() {
  if (node->next == node || link_type(node->next)->next == node) return;
  iterator first = begin();
  ++first;
  while (first != end()) {
    iterator old = first;
    ++first;
    transfer(begin(), old, first);
  }
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值