关联容器中的元素是按关键字来保存和访问的。与之相对,顺序容器是按它们在容器中的位置和顺序保存和访问的。
关联容器也是模板。为了定义一个map,我们必须指定关键字和值的类型。
与顺序容器类似,可以对一个关联容器的元素进行列表初始化。
- 按关键字有序保存元素
- map
当从map中提取一个元素时,会得到一个pair类型的对象。简单来说,pair是一个模板类型,保存两个名为first和second的公有数据成员。 - set
find调用返回一个迭代器,如果给定关键字存在,迭代器指向该关键字。否则,find返回尾后迭代器。 - multimap
- multiset
- map
- 无序集合
- unordered_map
- unordered_set
- unordered_multimap
- unordered_multiset
3.关联容器操作
set<string>::value_type v1; //v1是一个string
set<string>::key_type v2; //v2是一个string
map<string, int>::value_type v3; //v3是一个pair<const string, int>
map<string, int>::key_type v4; //v4是一个string
map<string, int>::mapped_type v5; //v5是一个int
3.1关联容器迭代器
当解引用一个关联容器迭代器时,我们会得到一个类型为容器的value_type的值的引用。对于map而言,value_type是一个pair类型,其first成员保存const的关键字,second成员保存值。
3.1.1set的迭代器是const的
虽然set类型同时定义了iterator和const_iterator类型,但两种类型都只允许读取set中的元素,但不能修改。
3.1.2遍历关联容器
mep和set类型都支持begin和end操作,我们可以用这些函数获取迭代器,然后使用迭代器来遍历容器。
3.1.3关联容器和算法
我们通常不对关联容器使用泛型算法。关键字是const这一特性意味着不能将关联容器传递给修改或重排容器元素的算法。
3.2添加元素
insert有两个版本,分别接受一对迭代器,或是一个初始化列表。对于一个给定的关键字,只有第一个带此关键字的元素才被插入到容器中。
vector<int> nums = {2, 4, 6, 2, 4, 6};
set<int> s;
s.insert(nums.cbegin(), nums.cend());
s.insert({1, 3, 5});
map<string, int> map;
map.insert({"key", 1});
map.insert(make_pair("key", 1));
3.2.1检查insert的返回值
map<string, int> map;
string s = "leetcode";
auto res = map.insert({s, 1}); //返回一个pair,pair的first是一个迭代器,指向具有给定关键字的元素,second是一个bool值
cout << res.second << endl; //输出1
auto ans = map.insert({s, 1});
cout << ans.second << endl; //输出0
3.3删除元素
c.erase(k) : 从c中删除每个关键字为k的元素。返回一个size_type值,指出删除的元素的数量
c.erase(p) : 从c中删除迭代器p指定的元素。p必须指向c中一个真实元素。返回一个指向p之后元素的迭代器
c.erase(b, e) : 删除迭代器对b和e所表示的范围中的元素,即删除[b, e),返回e
3.4map的下标操作
map和unordered_map容器提供了下标运算符和一个对应的at函数。
与其他下标运算符不同的是,如果关键字不在map中,会为它创建一个元素并插入到map中,关联值将进行值初始化。
c[k] : 返回关键字为k的元素;如果k不在c中,添加一个关键字为k的元素,对其进行值初始化
c.at(k) : 访问关键字为k的元素,带参数检查;若k不在c中,抛出一个out_of_range异常
3.4.1使用下标操作的返回值
对一个map进行下标操作时,会获得一个mapped_type对象;当解引用一个map迭代器时,会得到一个value_type对象。
与其他下标运算符相同的时,map的下标运算符返回一个左值。由于返回的是一个左值,所以我们既可以读也可以写元素。
3.5访问元素
注意:lower_bound和upper_bound不适用于无序容器。
如果lower_bound和upper_bound指向相同的迭代器,则关键字不在容器中,且两个迭代器都指向关键字可以插入的位置。
函数方法 | 作用 |
---|---|
c.find(k) | 返回一个迭代器,指向第一个关键字为k的元素,若k不存在,则返回尾后迭代器 |
c.count(k) | 返回关键字等于k的元素的数量 |
c.lower_bound(k) | 返回一个迭代器,指向第一个关键字不小于k的元素。[lower_bound, upper_bound) |
c.upper_bound(k) | 返回一个迭代器,指向第一个关键字大于k的元素。[lower_bound, upper_bound) |
c.equal_range(k) | 返回一个迭代器pair,表示关键字等于k的元素的范围。若k不存在,pair的两个成员均等于c.end() |
3.5.1对map使用find代替下标操作
对map和unordered_map类型,下标运算符提供了最简单的提取元素的方法。但是下标操作有一个严重的副作用:如果关键字还未在map中,下标操作会插入一个具有给定关键字的元素,其值为0。在这种情况下,应该使用find。