list

1.list的数据结构

       STL中的list不仅仅是一个双向链表,而且还是一个环状链表。所以它只需要一个指针就可以完整表现整个链表。

       list中有一个属性node指针,刻意指向了尾端的一个空白节点,这样就符合STL前开后闭区间,并且以下几个函数就交容易实现。

iterator begin(){return (link_type)((node*).next);}

iterator end(){return node;}

       相对与vectorstartfinishlist只需要一个属性node就能完成应有功能了。

2.list的操作

2.1. push_front和push_back

       双向链表,可以双向插入

2.2. pop_front和pop_back

       vector是没有pop_*操作的,但是list

2.3. erase

       listerase没有vector那么的复杂就是直观的删除元素。

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);
}
iterator erase(iterator first, iterator last) 
{
  while (first != last) erase(first++);
  return last;
}

2.4. clear

       vector不同listclear是遍历元素摧毁并收回空间的。

void clear()
{
  link_type cur = (link_type) node->next; // begin()
while (cur != node) // 遍历
{	
    link_type tmp = cur;
    cur = (link_type) cur->next;
    destroy_node(tmp); 	
  }
  // 恢复node原始状态
  node->next = node;
  node->prev = node;
}

2.5. remove    

       remove操作将数值为value的所有元素移除

template <class T, class Alloc>
void list<T, Alloc>::remove(const T& value)
{
  iterator first = begin();
  iterator last = end();
while (first != last) 
{	
    iterator next = first;
    ++next;
    if (*first == value) erase(first); 	// 找到就移除
    first = next;
  }
}

 

2.6. unique

    unique操作不是使得list中没有元素都独一无二,而是删除相同的连续元素,注意只有“连续且相同的元素”,才会被移除剩一个。

template <class T, class Alloc>
void list<T, Alloc>::unique() 
{
  iterator first = begin();
  iterator last = end();
  if (first == last) return;
iterator next = first;
while (++next != last) 
{
    if (*first == *next)
      erase(next);
    else
      first = next;
    next = first;
  }
}

2.7. transfer

       transfer并不是公开接口,而是list内部提供的一个所谓的迁移操作:将某连续范围内的元素迁移到某个特定位置之前。这个操作对splice,reverse,sort都很有帮助。技术上就是指针的移动而已:

void transfer(iterator position, iterator first, iterator last) 
{
if (position != last) 
{
      (*(link_type((*last.node).prev))).next = position.node;	    // (1)
      (*(link_type((*first.node).prev))).next = last.node;		    // (2)
      (*(link_type((*position.node).prev))).next = first.node;  	// (3)
      link_type tmp = link_type((*position.node).prev);			// (4)
      (*position.node).prev = (*last.node).prev;				    // (5)
      (*last.node).prev = (*first.node).prev; 					// (6)
      (*first.node).prev = tmp;								// (7)
    }
}

2.8. splice

       和transfer的效果类似,但是transfer是内部的算法,splice是对外的接口,所以splice的参数中为保证后面所用的迭代器范围版本有效,另外还有一个参数是迭代器范围所属的list的引用。

// 将 x 接合于 position 所指位置之前。x 必须不同于 *this。
void splice(iterator position, list& x) 
{
    if (!x.empty()) 
      transfer(position, x.begin(), x.end());
}
// 将 i 所指元素接合于 position 所指位置之前。position 和i 可指向同一個list。
void splice(iterator position, list&, iterator i) //注意第二参数
{
    iterator j = i;
    ++j;
    if (position == i || position == j) return;
    transfer(position, i, j);
}
  // 将[first,last) 內的所有元素接合于position 所指位置之前。
  // position 和[first,last)可指向同一个ist,
  // 但position不能位于[first,last)之內。
void splice(iterator position, list&, iterator first, iterator last)  
{
    if (first != last) 
      transfer(position, first, last);
}

2.9. reverse

       由于list是双向链表,所以reverse使用了插入法,而不是单链表常用的三指针法。

template <class T, class Alloc>
void list<T, Alloc>::reverse() 
{
  // 如果是空白链表或者只有一个元素,就不需要操作。
  // 使用 size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢。
  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);
  }
} 

2.10. merge

       merge操作是将x合并到*this上,两个list的内容都必须先经过递增排序

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();
  // 注意:前提是,两个 lists 都已经经过递增排序,
  while (first1 != last1 && first2 != last2)
if (*first2 < *first1)
{
      iterator next = first2;
      transfer(first1, first2, ++next);
      first2 = next;
    }
    else
      ++first1;
   if (first2 != last2) transfer(last1, first2, last2);
}

2.11. sort

       sort就是排序,但是list容器内自己定义了sort,这是因为list的迭代器是Bidirectional Iterator,而sort算法要求的是Random Access Iterator。所以对list进行排序不可以调用算法库的sort而需要调用list自带的接口sortlistsort也是采用快速排序。

template <class T, class Alloc>
void list<T, Alloc>::sort() 
{
 // 如果是空白链表或者只有一个元素,就不需要操作。
 // 使用 size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢。
  if (node->next == node || link_type(node->next)->next == node) return;
  // 一些新的 lists,作为中间存储
  list<T, Alloc> carry;
  list<T, Alloc> counter[64];
  int fill = 0;
while (!empty()) 
{
    carry.splice(carry.begin(), *this, begin());
    int i = 0;
while(i < fill && !counter[i].empty()) 
{
      counter[i].merge(carry);
      carry.swap(counter[i++]);
    }
    carry.swap(counter[i]);         
    if (i == fill) ++fill;
  } 
  for (int i = 1; i < fill; ++i) 
     counter[i].merge(counter[i-1]);
  swap(counter[fill-1]);
}

2.12. assign和swap

       当然list也有assignswap操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值