C++拾遗(七)——关联容器
关联容器(Associative containers)支持通过键来高效地查找和读取元素。两个基本的关联容器类型是 map 和set。map 的元素以键-值(key-value)对的形式组织:键用作元素在 map 中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。set 和 map 类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素。如果一个键必须对应多个实例,则需使用 multimap 或 multiset,这两种类型允许多个元素拥有相同的键。
map |
关联数组:元素通过键来存储和读取 |
set |
大小可变的集合,支持通过键实现的快速读取 |
multimap |
支持同一个键多次出现的 map 类型 |
multiset |
支持同一个键多次出现的 set 类型 |
pair 类型
- pair 包含两个数据值。与容器一样,pair 也是一种模板类型。但又与之前介绍的容器不同,在创建 pair 对象时,必须提供两个类型名:pair 对象所包含的两个数据成员各自对应的类型名字,这两个类型不必相同。
- 与其他标准库类型不同,对于 pair 类,可以直接访问其数据成员:其成员都是仅有的,分别命名为 first 和 second。只需使用普通的点操作符——成员访问标志即可访问其成员:
string firstBook;
// access and test the data members of the pair
if (author.first == "James" && author.second == "Joyce")
firstBook = "Stephen Hero";
- 除了构造函数,标准库还定义了一个 make_pair 函数,由传递给它的两个实参生成一个新的 pair 对象。
map 类型
- map 是键-值对的集合。map 类型通常可理解为关联数组(associative array):可使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
- 在使用关联容器时,它的键不但有一个类型,而且还有一个相关的比较函数。默认情况下,标准库使用键类型定义的 < 操作符来实现键(key type)的比较。所用的比较函数必须在键类型上定义严格弱排序(strict weak ordering)。所谓的严格弱排序可理解为键类型数据上的“小于”关系。用做 map 对象的键时,可使用任意一个键值来访问相应的元素。
- map 对象的元素是键-值对,也即每个元素包含两个部分:键以及由键关联的值。map 的 value_type 就反映了这个事实。该类型比前面介绍的容器所使用的元素类型要复杂得多:value_type 是存储元素的键以及值的 pair 类型,而且键为 const。在学习 map 的接口时,需谨记 value_type 是 pair 类型,它的值成员可以修改,但键成员不能修改。
map<K,V>::key_type | 在 map 容器中,用做索引的键的类型 |
map<K,V>::mapped_type | 在 map 容器中,键所关联的值的类型 |
map<K,V>::value_type | 一个 pair 类型,它的 first 元素具有 const map<K,V>::key_type 类型,而 second 元素则为 map<K,V>::mapped_type 类型 |
- 定义了 map 容器后,下一步工作就是在容器中添加键-值元素对。该项工作可使用 insert 成员实现;或者,先用下标操作符获取元素,然后给获取的元素赋值。在这两种情况下,一个给定的键只能对应于一个元素这一事实影响了这些操作的行为。
- 使用下标访问 map 对象
map <string, int> word_count; // empty map // insert default initialzed element with key Anna; then assign 1 to its value word_count["Anna"] = ;
对于 map 容器,如果下标所表示的键在容器中不存在,则添加新元素,这一特性可使程序惊人地简练:
// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int
string word; while (cin >> word)
8 ++word_count[word];
- map::insert 的使用
// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int
string word; while (cin >> word) {
// inserts element with key equal to word and value 1;
// if word already in word_count, insert does nothing
pair<map<string, int>::iterator, bool> ret =
word_count.insert(make_pair(word, )); if (!ret.second)
// word already in word_count
++ret.first->second; // increment counter
} - map 对象的迭代遍历
// get iterator positioned on the first element
map<string, int>::const_iterator
map_it = word_count.begin(); // for each element in the map
while (map_it != word_count.end()) {
// print the element key, value pairs
cout << map_it->first << " occurs "
<< map_it->second << " times" << endl;
++map_it; // increment iterator to denote the next element
}
set 类型
- set 容器只是单纯的键的集合。set 不支持下标操作符,而且没有定义 mapped_type 类型。在 set 容器中,value_type 不是 pair 类型,而是与 key_type 相同的类型。它们指的都是 set 中存储的元素类型。这一差别也体现了 set 存储的元素仅仅是键,而没有所关联的值。与 map 一样,set 容器存储的键也必须唯一,而且不能修改。
multimap 和 multiset 类型
- map 和 set 容器中,一个键只能对应一个实例。而 multiset 和 multimap类型则允许一个键对应多个实例。
- 注意到,关联容器 map 和 set 的元素是按顺序存储的。而 multimap 和multset 也一样。因此,在 multimap 和 multiset 容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放。以下介绍查找元素的几种策略。
- 使用 find 和 count 操作
// author we'll look for
string search_item("Alain de Botton"); // how many entries are there for this author
typedef multimap<string, string>::size_type sz_type;
sz_type entries = authors.count(search_item);
// get iterator to the first entry for this author
multimap<string,string>::iterator iter =
authors.find(search_item); // loop through the number of entries there are for this autho
for (sz_type cnt = ; cnt != entries; ++cnt, ++iter)
cout <<iter->second << endl; // print each title - 另一个更优雅简洁的方法是使用两个未曾见过的关联容器的操作:lower_bound 和 upper_bound。m.lower_bound(k) 返回一个迭代器,指向键不小于 k 的第一个元素m.upper_bound(k) 返回一个迭代器,指向键大于 k 的第一个元素。
// definitions of authors and search_item as above
// beg and end denote range of elements for this author
typedef multimap<string, string>::iterator authors_it; authors_it beg = authors.lower_bound(search_item),
end = authors.upper_bound(search_item); // loop through the number of entries there are for this author
while (beg != end)
{
cout << beg->second << endl; // print each title
++beg;
} - 最后,更为简洁的是使用equal_range操作。m.equal_range(k) 返回一个迭代器的 pair 对象。它的 first 成员等价于 m.lower_bound(k)。而 second 成员则等价于 m.upper_bound(k)
// definitions of authors and search_item as above
// pos holds iterators that denote range of elements for this key
pair<authors_it, authors_it> pos = authors.equal_range(search_item); // loop through the number of entries there are for this author
while (pos.first != pos.second)
{
cout << pos.first->second << endl; // print each title
++pos.first;
}
C++拾遗(七)——关联容器的更多相关文章
- STL之关联容器
关联容器包含map.set.multimap.multiset. 关联容器的特点是明显的,相对于顺序容器,有如下特点: 1.其内部是采用非线性的二叉树结构,具体的说是红黑树的结构原理实现的. 2.se ...
- STL_关联容器 VS C++ hashmap
红黑树和哈希表区别: http://m.blog.csdn.net/article/details?id=52133283 关于STL中关联容器的几个问题: (1)为何map和set的插入删除效率比用 ...
- C++学习基础四——顺序容器和关联容器
—顺序容器:vector,list,queue1.顺序容器的常见用法: #include <vector> #include <list> #include <queue ...
- C++ 关联容器
<C++ Primer 4th>读书笔记 关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素. 关联容器(Ass ...
- C++ Primer : 第十一章 : 关联容器之关联容器的迭代器和操作
关联容器的操作 除了和顺序容器定义的类型之外,关联容器还定义了一下几种类型: 关联容器额外的类型别名 key_type 此容器类型的关键字类型 mapped_type 每个关键字关联的类型, ...
- C++ Primer : 第十一章 : 关联容器之概述、有序关联容器关键字要求和pair类型
标准库定义了两种主要的关联容器:map和set map中的元素时一些关键字-值(key-value)对,关键字起到索引的作用,值则表示与索引相关的数据.set中每个元素只包含一个关键字,可以完成高效的 ...
- 使用multimap创建重复键关联容器
在“使用 <map> 库创建关联容器”一文中,我们讨论了标准库中的 map 关联容器.但那只是 map 容器的一部分.标准库还定义了一个 multimap 容器,它与 map 类似,所不同 ...
- Chapter11:关联容器
当用decltype来获得一个函数指针类型时,必须加上一个*来指出我们要使用一个给定函数类型的指针.decltype<CompareIsbn>*. map<string, int&g ...
- C++ 之关联容器 map
标准库定义了四种关联容器:map是其中之一(另外还有set.multimap.multiset).map的元素以键-值(key-value),在学了顺序容器之后,再学习关联容器,就比较比较好理解了. ...
随机推荐
- Java中的IO流(1)
字节流: //一个字节一个字节的读写 FileInputStream in=new FileInputStream("源文件"); FileOutputStream out=new ...
- redis和memcache的比较
1.数据类型支持不同 与Memcached仅支持key-value结构不同,Redis支持的数据类型更丰富,同时支持list.set.hash等数据结构的存储: 2.内存管理不同 在Redis中,并不 ...
- thymeleaf控制view的返回格式
package com.ailk.dd1.jike.web.config; import nz.net.ultraq.thymeleaf.LayoutDialect; import org.sprin ...
- CodeForces 1131G. Most Dangerous Shark
题目简述:从左到右依次有$n \leq 10^7$个Domino骨牌,高度为$h_i$,手动推倒他的花费为$c_i$.每个骨牌之间的距离为$1$.一个骨牌可以被向左或者向右推倒.当第$i$个骨牌被推倒 ...
- CodeForces - 1017D Round #502 D. The Wu(状压预处理)
D. The Wu time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
- 数据库路由中间件MyCat - 源代码篇(9)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 3.5 后端连接 3.5.1 后端连接获取与负载均衡 上一节我们讲了后端连接的基本建立和响应 ...
- shell初级-----构建基本脚本
使用多个命令 如果想要多个命令同时运行,可以把它们放在一行,用分号隔开. date;who 创建shell脚本文件 创建shell脚本时,必须在文件第一行指定要使用的shell #!/bin/bash ...
- (转)机器学习——深度学习(Deep Learning)
from:http://blog.csdn.net/abcjennifer/article/details/7826917 Deep Learning是机器学习中一个非常接近AI的领域,其动机在于建立 ...
- Codeforces Round #401 (Div. 2)【A,B,C,D】
最近状态极差..水题不想写,难题咬不动..哎,CF的题那么简单,还搞崩了= =.真是巨菜无比. Codeforces777A 题意:略. 思路: 构造出3!次变换,然后输出就好. Code: #inc ...
- uoj#38. 【清华集训2014】奇数国(线段树+数论)
传送门 不难看出就是要先求区间积,再求这个区间积的\(\varphi\) 因为\(\varphi(x)=x\times\frac{p_1-1}{p_1}\times\frac{p_2-1}{p_2}\ ...