对于源码的分析非常复杂,对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; } }
关于二分查找,在stl中有三个,下面博文介绍了这三个函数,有空会进行解析。