关联容器概述
- 顺序容器中的元素按其在容器中的顺序保存和访问,而关联容器中的元素则按关键字保存和访问
关联容器类型
map
- key - value 映射的集合,关键字不允许重复,且有序排列
#include <map>- 使用例子:
string word;
map<string, size_t> word_count; // 一个从字符串到计数的空 map
// 要定义一个 map,必须同时提供 key 和 value 的类型
while (cin >> word)
++word_count[word]; // 通过下标运算符将 word 的计数器加 1
// 如果 key 不在当前 map 中,下标运算符会创建一个新映射
for (const auto wc : word_count) // wc 的实际类型为 pair
cout << wc.first << " occurs " << wc.second
<< ((wc.second > 1) ? "times" : "time") << endl;
// wc.first 指向当前映射 wc 中的 key,wc.second 指向当前映射 wc 中的 valuemultimap
- key - value 映射的集合,关键字允许重复,且有序排列
#include <map>
unordered_map
- key - value 映射的集合,关键字不允许重复,无序排列
#include <unordered_map>
unordered_multimap
#include <unordered_map>- key - value 映射的集合,关键字允许重复,无序排列
set
- key 的集合,关键字不允许重复,且有序排列
#include <set>- 使用例子:
string word;
map<string, size_t> word_count;
set<string> exclude_articles = {"a", "an", "the", "A", "An", "The"}; // 需要剔除的冠词
while (cin >> word)
if (exclude_articles.find(word) == exclude_articles.end()) // 只统计不在 set 中的单词
// find(key) 返回一个迭代器,若 key 在 set 中,则返回指向 key 的迭代器,否则返回尾后迭代器
++word_count[word];multiset
- key 的集合,关键字允许重复,且有序排列
#include <set>
unordered_set
- key 的集合,关键字不允许重复,无序排列
#include <unordered_set>
unordered_multiset
- key 的集合,关键字允许重复,无序排列
#include <unordered_set>
关键字类型
- 对于有序容器,关键字类型必须定义了元素之间比较的方法
使用自定义的关键字比较操作
- 为了使用自定义的操作,必须在定义关联容器时同时提供关键字类型和比较操作的类型 —— 一种函数指针类型,指向自定义的比较函数
bool compare(const string & str1, const string & str2) {
return str1.size() < str2.size();
}
set<string> exclude1 = {"a", "an", "the", "A", "An", "The"};
set<string, decltype(compare)*> exclude2(compare) = exclude1;pair 类型
#include <utility>- 一个
pair包含两个public的数据成员,分别命名为first和second -
map的每个元素都是一个pair
关联容器操作
类型别名
-
key_type:关键字类型 -
mapped_type:map中值的类型 -
value_type:对于set,与key_type相同;对于map,为pair<const key_type, mapped_type>
迭代器
- 解引用一个迭代器返回一个
value_type类型的引用 -
map和set的关键字都是const的,不允许修改,因此迭代器也是const_iterator类型 -
map中的value可以修改
auto map_it = word_count.begin(); // map_it 的类型为 &pair<const string, size_t>
cout << map_it->first << " " << map_it->second;
map_it->first = "new key"; // ERROR!
++map_it->second;添加元素:insert()
向 map 或 set 添加元素
- 必须以
pair的形式向map添加元素:
word_count.insert({word, 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));- 对于不包含重复元素的关联容器,
insert()返回一个pair。pair的first成员是指向具有给定关键字的元素,second是一个bool值,指出元素是插入成功还是已经存在于容器中。如果元素已经存在于容器中,second为false,否则为true
向 multimap 或 multiset 添加元素
multimap<string, string> player;
player.insert({"LeBron James", "Cleveland Cavaliers"});
player.insert({"LeBron James", "Miami Heat"});
player.insert({"LeBron James", "Los Angeles Lakers"});
player.insert({"Dwayne Wade", "Cleveland Cavaliers"});
player.insert({"Dwayne Wade", "Miami Heat"});
player.insert({"Dwayne Wade", "Chicago Bulls"});- 对于允许重复关键字的容器,
insert()操作总是成功,并返回一个指向新元素的迭代器
删除元素:erase()
erase(key):删除所有关键字为key的元素,返回被删除元素的个数erase(iter):删除迭代器iter指向的元素,iter不能指向尾后元素;返回指向所删除元素之后的元素的迭代器erase(begin, end):删除迭代器范围内的元素,返回end
访问元素
map 和 unordered_map 的下标 [] 和 at():通过 key 获得 value
- 下标运算符不支持
multimap和unordered_multimap - 如果关键字不存在,则会创建一个元素并插入到
map中,并对value值初始化 - 由于下标运算符可能插入新元素,因此只能对非
const的map使用下标 - 对于
at(key),若key不存在,则抛出out_of_range异常 -
map的下标返回mapped_type类型的对象(即值),且是一个左值
在关联容器中查找元素
-
find(key):返回一个迭代器,指向第一个关键字为key的元素;若不存在,则返回尾后迭代器 -
count(key):返回关键字为key的元素数量 -
lower_bound(key):返回一个迭代器,指向第一个关键字不小于key的元素 -
upper_bound(key):返回一个迭代器,指向第一个关键字大于key的元素 -
equal_range(key):返回一个迭代器pair,第一个迭代器指向第一个关键字为key的元素,第二个迭代器指向最后一个关键字为key的元素之后的位置;若未找到,则两个迭代器都指向end()
















