关联容器的操作
除了和顺序容器定义的类型之外,关联容器还定义了一下几种类型:
key_type | 此容器类型的关键字类型 |
mapped_type | 每个关键字关联的类型,只 适用于map |
value_type | 对于set,与key_type相同 对于map,为pair<const key_type, mapped_type> |
关联容器的迭代器
auto map_it = words.begin(); map_it->first = "new key"; // 错误:关键字是const的
++map->second;
一个map的value_type是一个pair,我们可以pair的值,但不能改变pair的关键字。
set的迭代器时const的:虽然set定义了iterator和const_iterator类型,但是两种类型都只允许只读set的元素,与不能改变map元素的关键字一样,set的关键字也是const的。
- 关联容器和算法
添加元素
c.insert(v) | v是value_type类型的对象,args用来构造一个元素 |
c.emplace(args) | 对于map和set,只有当元素关键字不在c中时才会插入(或构造)元素,函数返回一个pair,包含一个迭代器,指向具有关键字的元素,以及一个指示插入是否成功的bool值。 对于multimap和multiset,总会插入(或构造)给定元素,并返回一个指向新元素的迭代器。 |
c.insert(b, e) | b和e是迭代器,表示一个c::value_type类型值的范围,il是这种值的花括号列表,函数返回void |
c.insert(il) | 对于map和set,只插入关键字不在c中的元素,而multimap(set)将范围中或列表中的元素全部插入 |
c.insert(p, v) | 类似insert(v)(或emplace(args)),但将迭代器p作为一个提示,指出从哪里开始搜索新元素应该存储的位置,返回一个迭代器,指向具有给定关键字的元素。 |
c.emplace(p, args) |
- 检测insert的返回值
map<string, size_t> words;
string word; while (cin >> word) { auto ret = words.insert({word, 1});
if (!ret.second)
++ret.first->second; // 增加计数
}
ret保存insert返回的值,是一个pair。
ret.first是pair的第一个成员,是一个map迭代器,指向具有给定关键字的元素。
ret.first->second 解引用此迭代器获取second值
++ret.first->second 递增该值
删除元素
c.erase(k) | 从c中删除每个关键字为k的元素,返回一个size_type值,指出删除的元素的数量 |
c.erase(p) | 从c中删除迭代器p指定的元素,p必须指向c中的一个真实元素,不能是c.end(),函数返回一个指向p之后的元素的迭代器,若p指向c的尾元素,则返回c.end() |
c.erase(b, e) | 删除迭代器对b和e所表示的范围的元素,返回e |
// 删除一个关键字,返回删除的元素数量
if (words.erase(removal_word))
cout << removal_word << "removed" << endl;
else
cout << removal_word << "not found" << endl;
对于保存不重复关键字的容器,参数为key_type的erase版本总是返回0或1,而对于保存可以重复关键字的容器,删除元素的数量可能大于1。
map的下标操作
c[k] | 返回关键字为 k的元素,如果k不在c中,添加一个关键字为k的元素,对其进行值初始化 |
c.at(k) | 访问关键字为k的元素,带参数检查:若k不在c中,抛出一个out_of_range异常 |
map<string, size_t> words;
// 插入一个关键字为Anna的云阿苏,关联值进行值初始化,然后将1赋予它
words["Anna"] = 1;
由于下标操作可能会插入元素,因此我们只能对非const的map或unordered_map使用下标操作
成员函数at在找不到关键字的时候抛出异常,因此我们可以这样做 : 当我们只是想在一个map或unordered_map中查找关键字为k的元素时,使用at成员函数; 如果我们还想插入这个不存在的关键字为k的元素时,就使用下标操作。
- 使用下标操作的返回值
访问元素
lower_bound和upper_bound不适用于无需容器
下标和at操作只适用于非const的map和unordered_map c.find(k); 返回一个迭代器,指向第一个关键字为k的元素,若k不在c中,返回尾后迭代器。
c.count(k); 返回关键字等于k的元素的数量,对于不允许重复关键字的容器,总是返回0或1
c.lower_bound(k); 返回一个迭代器,指向第一个关键字不小于k的元素
c.upper_bound(k); 返回一个迭代器,指向第一个关键字大于k的元素
c.equal_range(k); 返回一个迭代器pair,表示关键字等于k的元素的返回,若k不存在,pair的两个成员均等于c.end()
- 对map使用find操作代替下表操作
if (words.find(k) == words.end())
cout << "k is not in the map!" << endl;
- 在multimap或multiset中查找元素
string search_item("Alain de Botton"); // 要查找的作者
auto entries = authors.count(search_item); // 作者的著作
auto iter = authors.find(search_item); // 作者的第一本书 while (entries) {
cout << iter->second << endl;
++iter;
--entries;
}
- lower_bound 和 upper_bound
我们还可以用lower_bound和upper_bound,lower_bound接受一个关键字,返回指向第一个具有给定关键字的元素的迭代器,而upper_bound返回指向最后一个具有给定关键字的元素之后的元素的迭代器。
如果关键字不在容器中,则lower_bound 和upper_bound会返回相等的迭代器——指向一个不影响排序的关键字插入位置。如果我们查找的关键字具有容器最大的关键字,则此upper_bound返回尾后迭代器,如果关键字不存在且大于容器最大的关键字,则lower_bound和upper_bound都返回尾后迭代器。
for (auto beg = authors.lower_bound(serch_item), end = authors.upper_bound(search_item); beg != end; ++beg)
cout << beg->second << endl;
如果lowerbound和upperbound相等,则给定关键字不存在容器中。
- equal_range函数
for (auto pos = authors.equal_range(search_item); pos.first != pos.second; ++pos.first)
cout << pos.first->second << endl;