STL(三)

本文详细介绍了STL中的list,set,和map容器,包括它们的基本概念、构造方法、数据操作(如赋值、插入、删除、查找)、大小操作、数据存取以及排序规则,特别强调了自定义类型的排序和特定场景的应用实例。
摘要由CSDN通过智能技术生成

目录

一、list容器

1.基本概念

 2.构造函数

3.赋值和交换

4. 大小操作

5.插入和删除

6.数据存取

7.反转和排序

二、set容器

1.构造和赋值

2.大小和交换

3.插入和删除

4.查找和统计

5.set和multiet的区别

6. pair对组创建

7.指定排序规则

(1)内置类型指定

(2)自定义类型指定

 三、map容器

1.构造和赋值

2. 大小和交换

3.插入和删除

4.查找和统计

5.排序


 一、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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值