vector
头文件是#include,可以理解成不定长数组。
vector支持随机访问,如同数组操作,可以直接设a[i]访问下标i的位置。它不支持任意位置O(1)插入,这点也如同数组,不如链表插入方便,所以我们一般在vector末尾插入。
声明
vectora;
vectorb[100];
vectorc;(stru为结构体名)
size/empty
size()返回vetor的实际长度,0代表空;而empty()返回一布尔值,判断vector是否为空。
特别强调:所有的STL容器都支持这两个方法,作用也一样。
对于元素的引用一定要记住是左闭右开区间,即for(int i=0;i<a.size();i++)来引用。
clear
clear()清空vector。
迭代器
可以被理解成STL容器的”指针“,可以用”*“操作。使用方法如下:
vector<int>a;
vector<int>::iterator it;
for(it=a.begin();it!=a.end();it++)
cout<<*it<<endl;
以上代码作用等同于:
for(int i=0;i<a.size();i++)
cout<<a[i]<<endl;
front/back
front()返回vector的第一个元素,等价于*a.begin()、a[0]。
back()返回vector的最后一个元素,等价于*–a.end()、a[a.size()-1](注意减1)。
push_back/pop_back
a.push_bask(x)把元素x插入到vector a的末尾。
a.pop_back()删除vector a的最后一个元素,无值返回。
set/multiset
头文件是#include,set是“有序集合”,而multiset是“有序多重集合”。前者的元素不能重复,而后者可以包含若干个相同的元素。两者内部实现都是“红—黑树”,查询复杂度为O(lgn)。
强调set不支持“随机访问”,必须使用迭代器进行访问使用。
声明
seta;声明了一个去除了重复元素的从小到大的有序集合a。
multisetb;声明了一个允许重复且从小到大的集合b。
size/empty/clear
如同vetor操作,功能一致。
迭代器++/–
set::iterator it;
it++访问“下一个”元素
it–访问“上一个”元素
注意:只支持++和–操作,不支持+和-操作,且操作的时间复杂度为O(lgn)。
begin/end
a.begin()返回有序集合中最小元素给迭代器,不是具体值。
a.end()返回有序集合中最大的元素的“下一个”位置给迭代器,如果要返回最大值的位置,则要–a.end()(因为“左闭右开”原则)。
insert
a.insert(x)把一个元素x插入到集合a中,时间复杂度为O(lgn)。注意set和multiset关于重复元素的区别。
例如下面代码的功能是把n个元素插入到有序多重集合a中,并从小到大输出该集合的所有元素。时间复杂度为O(n*lgn),相当于进行了一次排序。
multiset<int>a;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
a.insert(x);
}
for(multiset<int>::iterator it=a.begin();it!=a.end();it++)
cout<<*it<<" "<<endl;
注意访问是使用迭代器操作,不能直接引用。
find
s.find(x)在集合s中查找等于x的元素,并返回指向该元素的迭代器。若不存在,则返回s.end()。时间复杂度为O(lgn)。
lower_bound/upper_bound
这两个函数的用法与find类似,但查找的条件不同,时间复杂度为O(lgn)。
s.lower_bound(x)查找>=x的元素中“最小”的一个,并返回指向该元素的迭代器。如果不存在返回s.end()。
s.upper_bound(x)查找>x的元素中“最小”的一个,并返回指向该元素的迭代器。如果不存在返回s.end()。
举个例子,输出multiset集合中元素为x的个数:
int sum=0;
int x;
cin>>x;
for(multiset<int>::itetator it=s.lower_bound(x);it!=s.upper_bound(x);it++)
{
sum++;
}
可以看出,lower_bound指向与x相等的“第一个”元素;而upper_bound指向与x元素相等的“最后一个”元素的下一个元素的迭代器。
erase
设it是一个set迭代器,s.erase(it)是删除集合s中迭代器it指向的元素,时间复杂度为O(lgn)。
设it是一个multiset迭代器,要删除该集合中所有等于x的元素,则写成:
while(it=s.find(x)!=s.end())
s.erase(it);
count
s.count()返回集合s中元素的个数。
map
头文件是#include
声明
格式为:map<key_type,value_type>name。
map<int,int>a;
map<string,int>b;
map<pair<int,int>,vector >t;
迭代器
map的迭代器与set一样,返回的是一个二元组pair<key_type,value_type>。
insert/erase/find
与set类似,分别为插入、删除、查找操作。insert的参数是pair<key_type,value_type>,erase的参数可以是pair或者是迭代器。
h.find(x)在map中查找key=x的二元组,找到则返回二元组的迭代器,没有找到则返回h.end()。
[]操作符
h[key]=value改变key对应的value,x=h[key]把key所映射的value返回给变量x。这是map应用最吸引人的地方,操作方便,时间复杂度为O(lgn)。
强调:若查找的key不存在,则执行h[key]后,h会自动新建一个二元组(key,zero),并返回zero的引用。这里的zero表示一个广义的“零”,如整数0、空字符串等。所以,如果反复查找的key都不存在,这样map会开设许多”无用“的zero,白白浪费空间。所以我们在用h[key]操作之前,必须用find方法检查key的存在性。
【实例】用map统计字符串出现的次数。
给定n个字符串,m个问题,每个问题询问一个字符串出现的次数。n,m<=20000,每个字符串的长度不超过20。
#include<bits/stdc++.h>
using namespace std;
int main()
{
map<string,int>h;
string str;
int n,m;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>str;
h[str]++;
}
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>str;
if(h.find(str)==h.end())
cout<<0;
else
cout<<h[str];
}
return 0;
}