STL的list是数据结构的双向链表,他的内存空间可以是不连续的,通过指针来进行数据的访问,它可以高效率的在任意地方删除和插入,插入和删除的时间复杂度都是O(1)。
vector:插入和删除操作少,随机访问元素频繁。
list:插入和删除频繁,随机访问较少。
在vector插入一个元素之后,这个元素后面的地址全部会改变,而list不会,地址不会连续。
由于地址不是连续的,所以当用迭代器访问元素时,不能使用迭代器++、+1之类的操作。
基本使用
构造与初始化
list<int> L;//声明一个存放int类型的链表
list<char> L;// 声明一个存放char类型的链表
list<string> L;//声明一个存放string类型的链表
list<int> L{1,2,3} //声明一个链表初始化为1,2,3
list<int> L(n) //声明一个n个元素的列表,每个元素都是0
list<int> L(n,m) //声明一个n个元素的列表,每个元素都是m
list<int> L(first, last) //声明一个列表,其元素的初始值来源于由区间所指定的序
//列中的元素,first和last是迭代器
-----------------------------------------------------------------------
插入
L.assign(n, val) //将L中的所有元素替换成n个val元素
L.push_back(n); //在L的尾部插入元素n
L.push_front(n);//在L的头部插入元素n
L.insert(it,100); //在it位置(即头部)插入100,
L.insert(it,2,100);//在it位置插入2个100,
L.insert(it,b.begin(),b.end());//在it位置插入b从开始到结束的所有位置的元素
//it为迭代器, insert会返回插入第一个元素的位置
----------------------------------------------------------------------
删除
L.erase(it); //将L中it位置的元素删除
L.erase(it1,it2); //将L中[it1,it2)之间的元素删除
L.pop_back(); //将L中最后一个元素删除
L.pop_front(); //将L中第一个元素删除
L.clear();//清空L中所有元素
L.unique();//删除相邻的重复元素
L.remove(n);//删除L中所有值为n的元素
L.resize(n);//取L中前n个元素,剩下的全部删除
L.resize(n,m);//分情况
//如果n大于原来的元素个数,后面补元素m若干个,补到L中n个元素为止
//如果n小于原来的元素个数, 取L中前n个元素,剩下的全部删除
--------------------------------------------------------------
访问
for(auto &x:L) cout<<x<<' ';//佛系遍历法,适合所有容器
list<int>::iterator it=L.begin(); cout<<*it;//访问第一个元素
next(it)//返回it的下一个元素的地址 cout<<*next(it); c++11
L.front();//返回L中第一个元素
L.back();//返回L的最后一个元素
---------------------------------------------------------------
查找
find(L.begin(),L.end(),n);//查找,返回L中第一次出现的n的迭代器
----------------------------------------------------------------
其他
L.size();//返回元素个数
L.empty();//是否为空
L.merge();//合并两个容器,前提要有序
L.begin();//返回头部迭代器
L.end();//返回尾部迭代器
L.swap(La);//交换两个容器
例题(hdu 1276):
Problem Description
某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
Input
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
Output
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
Sample Input
2
20
40
Sample Output
1 7 19
1 19 37
又是一发水题...主要目的是练练手,毕竟菜,嘤嘤嘤~
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n; //n组输入
while(n--){
int m;
cin>>m; //m个士兵
int k=2;
list<int> l; //定义链表l
for(int i=1;i<=m;i++)
l.push_back(i); //每个士兵代号存入链表
while(l.size()>3){
int num=1; //模仿第num个士兵
for(auto i=l.begin();i!=l.end();)
if(num++%k==0) i=l.erase(i); //如果是第k个就出列,链表里删除,i自动返回链表下一地址
else i++; //没删除就判断下个士兵
k==2?k=3:k=2; //每次从第二或者第三个交替
}
for(auto i=l.begin();i!=l.end();i++){
if(i!=l.begin()) cout<<" ";
cout<<*i; //输出剩下士兵编号
}
cout<<endl;
}
return 0;
}
STL大法好!!!吃饭去了~