list

list概述

相较于vector的连续空间,list就显得复杂的多,它的好处是每次插入或删除一个元素,就配置或释放一个元素空间。

list的节点(node)

STL list的节点(node)结构:
template < class T>
struct __list_node{
  typedef void* void_pointer;
  void_pointer prev;//型别为void*,其实可设为__list_node< T >*
  void_pointer next;
  T data
};

list的迭代器

list迭代器必须有能力指向list的节点,并有能力进行正确的递增、递减、取值、成员存取等操作。由于STL list是一个双向链表,迭代器必须具备前移、后移的能力,所以list提供的是Bidrectional iterators.
list的一个重要性质:插入操作(insert)和接合操作(splice)都不会造成原有的list迭代器失效。甚至list的元素的删除操作(erase),也只有“指向被删除元素”的那个迭代器失效,其他迭代器不受任何影响。

list的数据结构

SGI list不仅是一个双向链表,而且还是一个环状双向链表,所以它只需要一个指针,便可以完整表现整个链表。
这里写图片描述
是环状链表秩序一个标记,即可完全表示整个链表,只要刻意在环状链表的尾端加上一个空白节点,便符合STL规范址“前闭后开”区间。

list的构造与内存管理:constructor,push_back,insert

当我们以push_back()将新元素插入于list尾端时,此函数内部调用insert();
void push_back(const T& x){insert(end(), x);}
insert()是一个重载函数,有多种形式,其中最简单的一种如下,首先配置并构造一个节点,然后在尾端进行适当的指针操作,将新阶段插入进去。
//函数目的:在迭代器position所指位置插入一个节点,内容为x
iterator insert(iterator position const T&x){
link_type tmp = create_node(x);//产生一个节点(设置内容为x)
//调整双向指针,使tmp插入进去
   tmp->next = position.node;
   tmp->prev = position.node->prev;
   (link_type(position.node->prev))->next = tmp;
   position.node->prev = tmp;
   return tmp;
}
注意,插入完成后,新阶段将位于哨兵迭代器(标示出插入点)所指之节点的前方——这是STL对于“插入操作”的标准规范。
这里写图片描述
所谓插入指的是“插在…之前”

list的元素操作:push_front, push_back, erase, pop_front, pop_back, clear, remove, unique, splice, merge, reverse, sort

//插入一个节点作为头节点
void push_front(consst T& x){insert(begin(), x);}
//插入一个节点,作为尾节点
void push_back(const T& x){ insert(end(), x);}
//移除迭代器position所指节点
iterator erase(iterator position){
  link_type next_node = link_type(position.node->next);
  link_type prev_node = link_type(position.node->prev);
  prev_node->next = next_node;
  next_node->prev = prev_node;
  destroy_node(position.node);
  return iterator(next_node);
}
//移除头结点
void pop_front(){erase(begin);}
//移除尾结点
void pop_back(){
  iterator tmp = end();
  erase(–tmp);
}
//清除所有节点(整个链表)
template < class T, class Alloc>
void list< T, Alloc>::clear(){//遍历每个节点
  link_type cur = (link_type) node->next;
  while(cur != node){
    link_type tmp = cur;
    cur = (link_type) cur->next;
    destroy_node(tmp);//销毁(析构并释放)一个节点
  }
  //恢复node原始状态
  node->next = node;
  node->prev = node;
}
list内部提供一个所谓的迁移操作(transfer):将某连续范围的元素迁移到特定位置之前,这个操作为其他的复杂操作如splice, sort, merge等奠定良好的基础。
迁移操作就是将(first, last)内的所有元素移到position之前,过程如下图:
这里写图片描述
list公开提供的是所谓的接合操作(splice):将某连续范围的元素从一个list移动到另一个(或同一个)list的某个定点。
//将x结合于position所指位置之前,x必须不同于*this
void splice(iterator position, list& x){
  if(!x.empty()){
    transfer(position, x.begin(), x.end());
  }
}

//merge()将x合并到*this身上,两个lists的内容都必须先经过递增排序
template< class T, class Alloc>
void list< T, Alloc>::merge(list < T, Alloc>& x){
  iterator first1 = begin();
  iterator last1 = end();
  iterator first2 = x.begin();
  iterator last2 = x.end();
  while(first1 != last1 && first2 != last2){
     if(*first1 < *first2){
      iterator next = first2;
      transfer(first, first2, ++next);
      first2 = next;
    }
    else
      ++first;
    if(first2 != last2) transfer(last1, first2, last2);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值