标准库定义了两种主要的关联容器:map和set
map中的元素时一些关键字-值(key-value)对,关键字起到索引的作用,值则表示与索引相关的数据。set中每个元素只包含一个关键字,可以完成高效的关键字查询操作。
由map和set延伸出来一共8个关联容器,或者是一个map,或者是一个set,multi开头的是可以重复关键字的关联容器,unordered_开头的是无序关联容器。unordered_multi开头的是允许重复关键字的无序关联容器。
map和multimap定义在头文件
1.使用map:
map words;
string word;
while (cin >> word)
++words[word];
for (const auto elmt : words)
cout << elmt.first << elmt.second << endl;
最后,打印出words内容,map的元素类型时pair,first成员表示关键字,second成员表示值。
2. 使用set
map words;
set exclude = {"The", "But", "And", "Or"};
string word;
while (cin >> word)
if (exclude.find(word) == exclude.end())
++words[word];
定义关联容器
定义一个map时,我们必须既指明关键字类型又指明值的类型,定义一个set时,只需指明关键字类型就可以,因为set的关键字就是值。
而初始化一个map时,必须提供关键字类型和值类型,我们将一对关键字-值放在一个花括号里: { key, value};
一个map或set的关键字是唯一的,multimap和multiset没有这个限制,初始化一个multimap或multiset时,可以重复关键字:
vector vec;
for (vector::size_type i = 0; i < 10; ++i){
// 每个关键字重复一次
vec.push_back(i);
vec.push_back(i);
}
set st(vec.begin(), vec.end());
multiset mltst(vec.begin(), vec.end());
cout << vec.size() << endl; // 输出20
cout << st.size() << endl; // 输出10
cout << mltst.size() << endl; // 输出20
关联容器对关键字的类型有一定的要求,先讲有序容器, 关键字类型必须定义元素的比较方法,默认情况下,标准库使用关键字类型的 < 运算符来比较关键字。
传递给排序算法的可调用对象必须满足与关联容器中关键字一样的类型要求。
可以向算法提供我们自己定义的比较操作,类似的,我们也可以提供自己定义的操作来代替关键字的 < 运算符。所提供的操作必须在关键字类型上定义一个严格弱序
它具备以下性质:
实际编程中,重要的是,如果一个类型定义了行为正常的 < 运算符,则它可以用作关键字类型。
我们定义一个类叫 Sales_data, 它又一个成员函数为compareIsbn, 用来比较它的成员isbn, 则我们可以用map来保存一个Sales_data类:
bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs) {
return lhs.isbn < rhs.isbn;
}
map Smap(compareIsbn);
pair类型
pair类型定义在头文件
pair p; p是一个pair类型,对两个类型分别为T1和 T2的成员进行值初始化
pair p(v1, v2); v1和v2分别对p的first和second成员进行初始化
pair p = {v1, v2}; 等价于p(v1, v2)
make_pair(v1, v2); 函数返回一个用v1和v2初始化的pair,pair的类型从v1和v2推断出来
p.first; 返回p的名为first(共有的)的数据成员
p.second; 返回p的名为second(共有的)的数据成员
p1 relop p2 关系运算符(< <= > >=)按字典序定义: 当p1.first < p2.first或 !(p2.first < p1.first) && p1.second < p2.second 成立时,p1 < p2
p1 == p2 当first和second成员分别相等时,两个pair相等。
p1 != p2
假如一个函数返回pair类型,我们可以这样返回:
pair
process(vector& v) {
if (!v.empty())
return {v.back(), v.back().size()}; // 列表初始化
else
return pair(); // 隐式构造返回值
}
if (!v.empty())
return make_pair(v.back(), v.back().size());