目录
一、list容器
1.基本概念
list将数据进行链式存储。链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
链表的组成:链表由一系列结点组成。结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
list优点:采用动态存储分配,不会造成内存浪费和溢出;可以对任意位置进行插入删除元素。缺点:容器遍历速度没有数组快,占用空间比数组大。
STL中的链表是一个双向循环链表。 由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器。
list有一个重要的性质,插入操作和删除操作不会造成原有list迭代器的失效,这在vector是不成立的。
STL中List和vector是两个最常被使用的容器,各有优缺点
2.构造函数
list构造方式同其他几个STL常用容器,熟练掌握即可。
3.赋值和交换
list赋值和交换操作能够灵活运用即可。
4. 大小操作
5.插入和删除
6.数据存取
list不能使用[]或at访问容器中的元素。原因是list本质是链表,不是用连续线性空间存储数据,迭代器也是不支持随机访问的。
7.反转和排序
对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序。
将Person自定义数据类型进行排序,Person有姓名、年龄、身高这三个属性。
8.士兵队列训练问题
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int n,nums;
void solve(list<int> &l,int key){
int i=0;
list<int>::iterator it=l.begin();
while(it!=l.end()){//报完数以后才判断size是否小于3,而不是士兵小于3人以后立刻停止报数
i++;
if((i%key==0)){it=l.erase(it);}
else{it++;}
}
}
int main()
{
while(cin>>n){
for(int i=0;i<n;i++){
cin>>nums;
list<int> l;
for(int i=1;i<=nums;i++)
l.push_back(i);
while(l.size()>3){
solve(l,2);
if(l.size()<=3)//报完数以后判断一下 如果不超过3人则退出循环
break;
solve(l,3);
}
for(list<int>::iterator it=l.begin();it!=l.end();it++)
cout<<*it<<" ";
cout<<endl;
}
}
return 0;
}
二、set容器
1.构造和赋值
所有元素在插入容器时自动被排序。set/multiset属于关联式容器,底层结构是用二叉树实现的。
set不允许容器中有重复的元素,multiset允许容器中有重复的元素。
2.大小和交换
set不支持resize,因为如果resize过长,以0或指定数填充和set不允许重复的特点相矛盾。
3.插入和删除
insert插入,erase删除,clear清空
4.查找和统计
5.set和multiet的区别
set不可以插入重复数据,而multiset可以;set插入数据的同时会返回插入结果,表示插入是否成功;multiset不会检测数据,因此可以插入重复数据。
6. pair对组创建
成对出现的数据,利用对组可以返回两个数据。
7.指定排序规则
(1)内置类型指定
利用仿函数改变排序规则,仿函数是定义了一个含有operator()成员函数的对象。
目前不需要了解这个原理,知道这么用就行了。
(2)自定义类型指定
8.{A} + {B}
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int main()
{
int key;
while(cin>>n>>m){
set<int> s;
for(int i=0;i<n;i++){
cin>>key;
s.insert(key);
}
for(int i=0;i<m;i++){
cin>>key;
s.insert(key);
}
for(set<int>::iterator it=s.begin();it!=s.end();it++)
cout<<*it<<" ";
cout<<endl;
}
return 0;
}
9. MANAGER
可以看出题目中的队列需要有自动排序的功能,且允许有重复元素。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int m,n;
multiset<int> s,arr;
int main()
{
while(cin>>m>>n){
char a;
int key=1,nums=0,t,b;
s.clear();
arr.clear();
for(int i=0;i<n;i++){
cin>>t;
arr.insert(t);//移除列表
}
while(cin>>a&&a!='e'){
if(a=='a'){
cin>>b;s.insert(b);
}
else if(a=='r'){
nums++;
if(nums==*arr.begin()&&s.empty()){//移除请求的序号在列表中且但s为空
cout<<"-1"<<endl;
arr.erase(arr.begin());
continue;
}
if(key==1){
if(nums==*arr.begin()){cout<<*s.begin()<<endl;arr.erase(arr.begin());}
s.erase(s.begin());//移除成本最低的
}
else{
if(nums==*arr.begin()){cout<<*(--s.end())<<endl;arr.erase(arr.begin());}
s.erase(--s.end());//移除成本最高的
}
}
else{
cin>>b;key=b;
}
}
cout<<endl;
}
return 0;
}
三、map容器
map中所有元素都是pair。pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)。所有元素都会根据元素的键值自动排序。
map/multimap属于关联式容器,底层结构是用二叉树实现。
优点:可以根据额key值快速找到value值。
map和multimap区别:map不允许容器中有重复的key值,multimap允许有重复的key值。
1.构造和赋值
map中所有元素都是成对出现,插入数据时要使用对组。
2. 大小和交换
统计大小size;判空empty;交换swap
3.插入和删除
map插入方式很多种,记住其一即可
4.查找和统计
5.排序
同set容器默认以key值升序,利用仿函数排序。(以下代码operator前少了个bool)
6. Hardwood Species
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int m,n;
map<string,int> M;
string str;
int main()
{
while(getline(cin,str)){
if(str.empty())
break;
if(M[str])
M[str]+=1;
else M[str]=1;
}
int sum=0;
for(map<string,int>::iterator it=M.begin();it!=M.end();it++)
sum+=it->second;
for(map<string,int>::iterator it=M.begin();it!=M.end();it++){
double percentage = (double)(it->second) / sum * 100.0;
cout<<it->first<<" "<<fixed <<setprecision(4)<<percentage<<endl;
}
return 0;
}
7.Double Queue
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int a,b,c;
int main()
{
map<int,int> m;
while(cin>>a&&a!=0){
if(a==1){
cin>>b>>c;
m.insert(make_pair(c,b));//可以假设列表中没有其他相同客户或相同优先级的请求
}
else{
if(m.empty()){cout<<"0"<<endl;continue;}
if(a==2) {cout<<(--m.end())->second<<endl;m.erase(--m.end());}
else {cout<<m.begin()->second<<endl;m.erase(m.begin());}
}
}
return 0;
}
8. 水果
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int n,m,nums;
string a,b;
int main()
{
cin>>n;
for(int i=0;i<n;i++){
map<string, map<string,int> > M;
cin>>m;
for(int i=0;i<m;i++){
cin>>a>>b>>nums;
map<string,map<string,int> >::iterator pos=M.find(b);//查找有无这个地名
if(pos!=M.end()){
map<string,int>::iterator pos1=(pos->second).find(a);//查找这个地名中有无这个水果
if(pos1!=(pos->second).end())pos1->second+=nums;//有水果再加上数量
else (pos->second).insert(make_pair(a,nums));//无水果等于数量
}else{
map<string,int> M1;M1.insert(make_pair(a,nums));//没有这个地名,插入数据
M.insert(make_pair(b,M1));
}
}
for(map<string, map<string,int> >::iterator it=M.begin();it!=M.end();it++){//遍历
cout<<it->first<<endl;
for(map<string,int>::iterator it1=(it->second).begin();it1!=(it->second).end();it1++){
cout<<" |----"<<it1->first<<"("<<it1->second<<")"<<endl;
}
}
}
return 0;
}