关联容器概述
- 顺序容器中的元素按其在容器中的顺序保存和访问,而关联容器中的元素则按关键字保存和访问
关联容器类型
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 中的 value
multimap
- 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()