链表和list
咳咳,不是每一朵鲜花都能代表爱情,但是玫瑰做到了;不是每一颗树都能耐的住干渴,但是白杨做到了;也不是每一个人都会追求上进,挑战自我,但是我相信我们也能做到。今天给大家带来的是c++容器,list链表。
- list作为c++里面的容器哈,它是一个双向链表,空间可以不连续,通过指针进行数据的访问哈,他可以高效率的完成在任意地方的删插改。
- 但是list链表不支持随机访问哦!
- 然后我们来看看他的用法:
写法 | 说明 |
---|---|
list < int > mlist; | 定义一个链表mlist |
push_back(n); | 尾部插入值n |
push_front(n); | 首部插入值n |
pop_back(); | 尾部删除 |
pop_front(); | 首部删除 |
insert(pos,elel); | pos位置插入elel元素 |
clear(); | 链表清空 |
erase(pos); | 删除pos位置的元素 |
remove(elem); | 删除所有elem元素 |
size(); | 返回链表大小 |
empty(); | 判断链表是否为空 |
resize(num); | 重新定义链表大小 |
front(); | 返回第一个元素 |
back(); | 返回最后一个元素 |
reverse(); | 将整个链表进行反转 |
sort(); | 将整个链表进行排序 |
- ok,基本用法已列出来了,现在我们来用用看;
- 咳咳, 然后我们来看看插入哈,这里得说一下哈,插入函数和删除函数呢,你不能随意的使用加号,因为list链表是不支持随机访问的,只能用迭代器一次性遍历过去,然后遇到的时候再进行插入或者删除。
- 是不是看起来有点麻烦,可能对我们而言是很麻烦,但是对于计算器来说,它是很舒服的。
- 相对于vector数组而言,如果随机访问数组的元素很多,那就需要多用vector数组,但是对于一些插入、删除操作多的时候,链表的效率就体现出来了。
- 例子走起:
hdu 1276 “士兵队列训练问题”
题目链接:点我了解题目(这是一个链接)
大意:
某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
输入样例:
2
20
40
输出样例:
1 7 19
1 19 37
- 先按照两个踢出去一个的方式遍历一次,然后再按照三个踢出去一个的方式遍历一次,直到这个链表的大小小于三的时候,输出剩余的士兵。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin >> n;
while(n--){
list<int > mlist;
cin >> m;
for(int i=1;i<=m;i++)mlist.push_back(i);
int k = 2;
while(mlist.size()>3){
int num=1;
for(list<int >::iterator it = mlist.begin();it!=mlist.end();){
if(num++%k==0)it = mlist.erase(it); //注意这里:erase方法,返回删除元素下一个位置
else it++;
}
k == 2 ? k=3 : k=2;
}
for(list<int >::iterator it=mlist.begin();it!=mlist.end();it++){
if(it!=mlist.begin())cout << " ";
cout << *it;
}
cout << endl;
}
return 0;
}
- 看起来可能有点复杂,可有些时候还是很有用的。
- 要记住哦,erase方法返回的是删除的元素后一个元素的位置,这样我们在使用erase删除元素的时候,只需要用 it = mlist.erase(it); 这样子就行了。
- 咳咳,今天就到这里吧,咱们set集合见。