map是关键字-值对的集合。关键字起到了索引作用,值则表示与索引相关的数据。set则只是关键字的集合,支持高效的关键字查询操作。使用map的实例程序如下:
map<string,std::size_t> word_count;//定义一个string到size_t的map
set<string> exclude={"the","but","and","or","an","a"};//定义忽略统计的单词的set
string word;
while(cin>>word)
{
if(exclude.find(word)==exclude.end())//如果统计的单词不再set当中
++word_count[word];//统计单词的次数加1
}
for(const auto &w:word_count)
cout<<w.first<<" occurs"<<w.second<<((w.second)>1?" times":" time")<<endl;
对于map和set,其关键字必须是唯一的,但是multimap或multiset则允许多个元素具有相同的关键字。实例程序如下:
vector<int> ivec;
for(vector<int>::size_type i=0;i!=10;++i)//ivec保存重复的1~10
{
ivec.push_back(i);
ivec.push_back(i);
}
set<int> iset(ivec.begin(),ivec.end());//将ivec初始化set
std::multiset<int> miset(ivec.begin(),ivec.end());//将ivec初始化multiset
cout<<ivec.size()<<endl;//20
cout<<iset.size()<<endl;//10
cout<<miset.size()<<endl;//20
//证明了容器set的关键字是唯一的,不可重复的。而multiset关键字可以重复。
使用map和set的时候,其关键字类型必须是定义了严格弱序的,即定义了“<”函数,如果未定义,则可以为关键字类型定义一个比较函数。程序如下:
class A//类型A没有定义<函数
{
public:
int v;
}
bool cmp(A a1,A a2)//定义外部函数<
{
return a1.v<a2.v;
}
multiset<A,decltype(cmp)*> st(cmp);//使用自定义操作定义set
//定义multiset必须提供两个类型,关键字类型和比较操作类型(函数指针类型);
pair标准库类型定义子啊utility头文件中,一个pair保存两个数据成员。pair 的默认构造函数对数据成员进行值初始化。pair的操作如下:
//默认初始化
pair<string,int> val1;
cout<<val1.first<<" "<<val1.second<<endl;//"" 0
pair<string,int> val2={"a",3};//列表初始化
cout<<val2.first<<" "<<val2.second<<endl;//"a" 1
pair<string,int>val3=std::make_pair("c",2);//make_pair创建pair
cout<<val3.first<<" "<<val3.second<<endl;//"c", 2
cout<<(val2>val3)<<endl;// 0
关联容器的额外类型别名:
一个map的value_type是一个pair,我们可以改变pair的值,但不能改变关键字成员的值,因其为const类型。而set迭代器是const的,故set的元素是只读的。
遍历关联容器支持像vector一样使用begin和end操作,获取迭代器来遍历容器。程序如下:
map<string,std::size_t> word_count={{"hello",1},{"apple",2},{"world",3}};//定义一个string到size_t的map
auto map_it=word_count.cbegin();
while(map_it!=word_count.cend())
{
cout<<map_it->first<<" occurs "<<map_it->second<<((map_it->second)>1?" times":" time")<<endl;
++map_it;
}
向map添加元素有四种方法,如下代码。
/**向map插入元素的四种方法**/
map.insert({key,value});
map.insert(make_pair(key,value));
map.insert(pair<key,vaule>(key,vaule));
map.insert(map<key,vaule>::value_type(key,value));
insert操作返回的是一个pair,它的first成员时一个迭代器,指向具有给定关键字的元素,second成员是一个bool值,指出元素是否插入成功还是已经存在于容器中。
map<string,size_t> word_count;//定义一个string到size_t的空map
string word;
while(cin>.word)//输入单词
auto ret=word_count.insert({word,1});//插入单词到map,返回一个pair
if(!ret.second)//ret的second表示插入是否成功
++ret.first->second;//ret的first是一个元素的map,map->second是相应关键字的值。
关联容器提供了一个额外的erase操作,它接受一个key_type参数,删除匹配给定关键字的所有元素,返回实际删除的元素的数量。对于保存不重复关键字的容器,erase的返回值总是0或1。对于允许重复关键字的容器,删除的元素数量大于1.
if(map.erase(key_type))
// process 1
else
// process 2
map支持下标操作,其接受一个索引(关键字),获取与此关键字相关联的值。但是值得注意的是,如果关键字并不在map中,其会它创建一个元素并插入到map中,关联值会进行值初始化。当对于一个map进行下标操作时,会获得一个mapped_type对象,而当解引用一个map迭代器时,会得到一个value_type对象。
map<string,size_t> word_count;
word_count["apple"]=1;
//插入一个关键字为apple的元素,关联值进行值初始化(0),然后将1赋予个它。
cout<<word_count["apple"];//打印1
在关联容器中查找指定元素有如下操作:
c.find(k) : 返回key==k 迭代器
c.count(k) : 返回key==k的元素的数量
c.lower_bound(k) : 返回第一个key>=k的元素
c.upper_bound(k) : 返回第一个key>k的元素。
c.euqal_range(k) : 返回一个迭代器pair, 它的first成员等于c.lower_bound(k) ,second成员等于c.upper_bound(k)。
map<string,size_t> mp={{"a",1},{"b",2},{"c",3},{"d",8}};
auto it1=mp.find("a");//map<string,size_t>::iterator
cout<<it1->second<<endl;//1
int it2=mp.count("d");//map<string,size_t>::iterator
cout<<it2<<endl;//1
auto it3=mp.lower_bound("b");//map<string,size_t>::iterator
cout<<it3->second<<endl;//2
auto it4=mp.upper_bound("a");//map<string,size_t>::iterator
cout<<it4->second<<endl;//2
//pair<map<string,size_t>::iterator,map<string,size_t>::iterator>
autoit5=mp.equal_range("c");
cout<<it5.first->second<<endl;//3