list介绍
STL的list是一个双向链表,插入删除的复杂度为O(1),不像vector,list是有多少元素使用多少空间,不会存在浪费的情况。
list细节:
1. list的迭代器不能像vector一样,以普通指针作为迭代器,因为双向链表的迭代器是双向迭代器,不是随机访问迭代器
2. 和vector不一样,list的插入、删除等操作不会造成其他迭代器失效(但被操作的迭代器可能失效)。
3. SGI STL的实现版本中,list是一个环状双向链表,因此只需要一个指针,就可以展现整个链表。通过让这个指针指向一个置于尾端的空白节点,list的很多函数都能轻易完成。比如这些函数(node为这个指针的名称)
iterator begin(){ return (*node).next;}
iterator end() {return node;}
bool empty(){return node->next == node;}
4. list的插入操作一般是插入在指定位置之前。
5. list内部提供一个所谓迁移操作(transfer)的非公开接口:将某连续范围的元素迁移到某个特定位置之前。这个操作为其他复杂操作入splice,sort,merge等奠定良好的基础。伪代码为:
void transfer(iterator position, iterator first, iterator last){
if(position!=last){
last.prev.next = position;
first.prev.next = last;
position.prev.next = first;
temp = position.prev;
position.prev = last.prev;
last.prev = first.prev;
first.temp = temp;
}
}
6. 值得一提的还有list内部实现的sort函数,list::sort是用非递归的归并排序实现的,伪代码如下:
template<class T, class Alloc>
void list<T,Alloc>::sort(){
//空链表或只有一个元素,则不进行操作
if(node->next == node || link_type(node->next)->next == node)
return;
list<T,Alloc> carry; //用于每次从待排序list中取元素
list<t,Alloc> counter[64];//用于存放待merge的非递减list
int fill = 0;
while(!empty()){
carry.splice(carry.begin(), *this, begin());//每次从待排序list中取一个数
int i = 0;
while(i < fill && !counter[i].empty()){ //将counter里面的数据进行合并
counter[i].merge(carry);
carry.swap(counter[i++]);
}
carry.swap(counter[i]);
if (i == fill) ++fill; //如果i到了当前最大合并层,增加合并层数
}
for(int i = 1; i < fill; ++i){
counter[i].merge(counter[i-1]);
}
swap(counter[fill-1]); //将最后合并的结果换到list中
}
对于list归并排序有疑惑的,请移步:http://www.cnblogs.com/avota/p/5388865.html
不得不说,SGI STL的接口设计一环扣一环,真的很简洁高效,十分值得学习借鉴。