对于源码的分析非常复杂,对STL的学习暂时留存

这里简单罗列一些容器的使用和操作。

(1)顺序容器

1、array

//array具有固定大小
//初始化:
array<int,42> a1;

array<int,3>  a2 = {1,2,3} //列表初始化

array<int,3> a3 = {1} //内部{1,0,0}

Tip:内置数组类型不允许copy和赋值,但是array可以

int a[3]  = {1,2,3};
int b[3] = a //不行
------------------------
array<int,3> a = {1,2,3};
array<int,3> b = a; //ok,类型匹配即可

2、操作

  初始化vector

vector<int> a(n); //初始化了n个值,元素为0;
vector<int> a(n,1); //初始化了n个值,元素为1;

(非array)添加元素

forward_list 有自己专属版本的insert和emplace,也不支持push_back和emplace_back

vector和string不支持push_front和emplace_front。

c.push_back(k)  //在c尾部创建一个值为t或由args创建的元素,返回void
c.emplace_back(args)

通常使用push_back()向容器中加入一个右值元素(临时对象)时,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放入容器中。原来的临时变量释放。这样造成的问题就是临时变量申请资源的浪费。 
引入了右值引用,转移构造函数后,push_back()右值时就会调用构造函数和转移构造函数,如果可以在插入的时候直接构造,就只需要构造一次即可。这就是c++11 新加的emplace_back。

关于俩者的区别。

c.push_front(t)//在c头部创建一个值为t或者...,返回void
c.emplace_front(args)

//vector和string没有这俩操作
//stack、queue、list是有的
//forword_list 专属版本

插入元素

c.insert(p,t)
c.emplace(p,args)

//在迭代器p指向的元素之前创建一个值为t或由args创建的元素,返回指向新添加的元素的迭代器。

c.insert(p,n,t)

//同上,但是插入n个值为t的元素,返回指向第一个添加的元素的迭代器,如果n为0,返回p。

c.insert(p,b,e)

//在迭代器b和e指定的范围内的元素插入到迭代器p指向的元素之前。b和e不能指向c中的元素,返回指向新添加的第一个元素的迭代器,空,则返回p。

c.insert(p,i1)

//i1是一个花括号包围的元素值列表,讲这些给定值插入迭代器p指向的元素前,返回指向新添加的第一个元素的迭代器,空,返回p

 

访问元素

//back不适用与forward_list
c.back();
c.front


//at操作和下标操作只适用于string,vector,deque和array
c[n]
c.at[n]

删除元素

//不适用与array,会改变array大小
//forward_list有特殊版本的erase
//forward_list不支持pop_back;
//vector和string不支持pop_front

c.pop_back()  //返回void,删除尾元素
c.pop_front()  //返回void ,删除首元素
c.erase(p)//删除迭代器p指定元素,返回一个指向被删除元素之后的迭代器,如果p指向尾元素,返回尾后迭代器(off-the-end),若p是尾后迭代器,无定义

e.erase(b,e) //删除范围内元素,返回指向最后一个呗删除元素之后的有迭代器。若e本身是尾后迭代器,则函数返回尾后迭代器。


c.clear() //删除c中所有元素,返回void

 

 

2、特殊的forward_list

//使用到再补充,来自primer c++ 5 p313页

 

 

(2)关联容器

map/set/multimp/multiset以及它们加前缀unordered的版本。

//定义

map<string,string> a;//空容器
map<string,sting> b = 
{{"studenta","A"},
  {"studentb","B"}};//{key-value}


set<string> b;



//找到元素容量

 b.size();//unordered_set等

pair类型

pair保存俩个数据成员
pair<string,string> a;//数据成员是public的,分别命名为first和second,可以访问它们。



pair<T1,T2> P;
pair<T1,T2> P(v1,v2)
pair<T1,T2>p = {v1,v2}  //等价于p(v1,v2)


make_pair(v1,v2);//返回一个pair
p.first
p.second

迭代器相关

cbegin()和begin的区别是,前者返回一个const_iterator,可以++等,但不可以修改值

遍历使用方法

auto map_it = a.cbegin(); //a是一个map

while(map_it !=a.cend()
{
    cout<<map_it->first<<map_it->second<<endl;
    map_it++;
}

添加元素方法(关联容器)

c.insert(v)  //v是一个value_type类型的对象。元素类型是pair
c.emplace(args)//对于map和set来说,只有关键字不在,才会插入,返回一个pair,包含一个迭代器,指向具有指定关键字的元素,以及一个是否插入成功的bool值,而multi系列,总会插入,并返回一个指向新元素的迭代器。
//举个例子

word_count.insert({wrod,1});
word_count.insert(make_pair(word,1));
word_count.insert(pair<string,size_t>{word,1});
word_count.insert(map<string,size_t>::value_type(word,1));


c.insert(b,e)
c.insert(il)   // 同之前顺序容器类似。

删除元素

c.erase(k)  //删除每个关键字为k的元素

c.erase(p)  // 删除迭代器p指定的元素。返回指向p之后的元素迭代器

c.erace(b,e)//删除范围,返回e。

下标操作

c[k] //返回关键字为k的元素,如果k不在c中,添加一个关键字为k的元素,对其值初始化

c.at[k]  //访问关键字为k的元素,k不在,返回一个异常:out_of_range

访问操作

c.find(k) //返回一个迭代器,指向第一个关键字为k的元素,若k不在容器中,返回尾后迭代器

  unordered_set<char> lookup;

  lookup.find(s[i]) != lookup.end();//查找s[i]是不是在容器内。不在的话,就会返回尾后迭代器,也就是lookup.end(),这题可以看leetcode第三题。

c.cout(k) //返回关键字等于k的元素数量,对于不允许重复的,值要么0要么1


//注意lower_bound和upper_bound不适用于无序容器
c.lower_bound(k)  //返回一个迭代器,指向第一个关键字不小于k的元素,也就是大于等于

c.upper_bound(k) //返回一个迭代器,指向第一个关键字大于k的元素

c.equal_range(k) //返回一个迭代器pair,表示关键字等于k的元素的范围,若k不存在,pair的俩个成员均等于c.end();

 

 

(3)最后的最后,放上一道网易的编程体,涉及到map容器的使用。

 

链接:https://www.nowcoder.com/questionTerminal/d73554145e4f443bb7d0a99d51dd6e5f来源:牛客网

为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。

 

输入描述:

每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。


输出描述:

对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。


示例1



输入


3 3 1 100 10 1000 1000000000 1001 9 10 1000000000




输出


100 1000 1001





#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
  
int main()
{
    int N,M;
    cin >> N >> M;
    unordered_map<int,int> work;
    vector<int> Di;
    for(int i=0;i<N;i++)
    {
        int difficulty,Pi;
        cin>>difficulty>>Pi;
        Di.push_back(difficulty);
        work[difficulty] = Pi;
        //work.insert(pair<int,int>(Di,Pi));
    }
     
    //转换vector,使用vector做二分排序需要先排序,这里是升序
    sort(Di.begin(), Di.end());
     
    //替换掉高难度低报酬
    int pay = 0;
    for(auto iter = Di.begin();iter<Di.end();iter++)
    {
        if(pay < work[*iter])
            pay = work[*iter];
        else
            work[*iter] = pay;
    }
     
    //有序,二分查找找到最合适的
    for(int j =0;j<M;j++)
    {
        int Ai;
        cin>>Ai;
        auto iter =  upper_bound(Di.begin(),Di.end(),Ai);
        iter--;
        pay = work[*iter];
        cout<<pay<<endl;
    }
      
}