关联容器的类型:
1、map 关联数组,元素通过键来存储和读取,以键值(key-value)对的形式组织
2、set 大小可变的集合,支持通过键实现的快速读取
3、multimap 支持同一个键多次出现的 map 类型
4、multiset 支持同一个键多次出现的 set 类型
set 和 map 类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素。
如果一个键必须对应多个实例,则需要使用 multimap 或者 mulitset 类型
定义在 utilitiy 头文件中的 pair 类型
pair<T1, T2> p1 | 创建一个空的 pair 对象, 它的两个元素分别是 T1 和 T2 类型,采用值初始化 |
---|---|
pair<T1, T2> p1(v1, v2) | 创建一个空的 pair 对象 两个元素类型分别是 T1 和 T2 类型, 第一个初始化为 v1,第二个初始化为 v2 |
make_pair(v1, v2) | 以 v1 和 v2 值创建一个新的 pair 对象, 其元素类型分别是 v1、v2的类型 |
p1 < p2 | pair 对象之间的小于运算 p1.first < p2.first 或者 !(p2.first < p1.first) && p1.second<p2.second,则:true |
p1 == p2 | p1、p2 的 first 和 second 成员依次相等,则 p1、p2 相等 |
p.first | 返回 p 中名为 first 的数据成员 |
p.second | 返回 p 中名为 second 的数据成员 |
pair 包含2个数据值。与容器一样,是一种模板类型。
pair 类的成员都是公有的,可以直接访问数据,分别命名为 first、 second
pair<string, vector<int> > word_count;
pair<string, string> author("James", "Joyce");
typedef pair<string, string> Author;
Author zhang("Zhang", "San");
Author li("Li", "Si");
if(zhang.first=="Zhang" && zhang.second=="San")
cout << "Found Author ZhangSan" << endl;
string first = "Mo", second = "Yan";
Author mo = make_pair(first, second);
map<k, v> m; | 创建一个名为 m 的空 map 对象,键值类型分别为 k、v |
---|---|
map<k, v> m(m2) | 创建 m2 的副本 m, m和m2 必须有相同的键类型、值类型 |
map<k, v> m(b, e) | 创建 map 类型的对象 m,存储迭代器 b 和 e 标记的范围内所有元素的副本 元素类型必须能够转换为 pair<const k, v> |
键类型必须定义 < 操作符,而且是 严格弱排序的,即,键类型数据上的小于关系。
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 类型 |
value_type 是 pair 类型,值成员可以修改,键成员不能修改
map 类额外定义的类型别名,
map<string, int>::key_type 是 string 类型,
map<string, int>::value_type 是 int 类型
map<string, int> word_count;
word_count["Anna"] = 1;
// 上述代码,执行过程:
// 1、在word_count 查找 "Anna",未找到
// 2、插入新的键值对,键为"Anna",值初始化 0
// 3、读取新插入的键值对,然后赋值为1
// 用下标访问 map 的情况,不同于数组和vector,
// 下标访问 map 中不存在的元素,将导致在该 map 中增加一个响应元素
vector 的下标操作返回的类型,和 vector迭代器解引用 获得的类型相同。
但是,
map 的下标操作返回左值,是 mapped_type 类型,
而 map 迭代器返回 value_type 类型,
包含 const key_type 、 mapped_type 的 pair 对象
// 此例演示了 map 类型,特殊的下标行为在编程中的意义
map<string, int> word_count;
string word;
while(cin >> word)
++word_count[word];
m.insert(e) | e 是一个 m 上的 value_type 类型的值。 如果 e.first 不在 m 中,则,插入新元素,值为 e.second 如果 e.first 已存在,m 不变。 该函数返回一个pair 类型的对象, 包含,指向键为 e.first 的元素的 map 迭代器, 和 一个bool 类型的对象,表示是否成功插入元素 |
---|---|
m.insert(beg, end) | beg 和 end 是标记元素范围的迭代器, 其中元素必须为 m.value_type 类型的键值对。 对于该范围内的所有元素,如果它的键在 m 中不存在, 则插入该键值对。返回 void 类型 |
m.insert(iter, e) | e 是一个 m 上的 value_type 类型的键值对。 如果 e.first 在 m 中不存在,则创建新元素, 并以迭代器 iter 为起点搜索新元素存储的位置。 返回一个迭代器,指向 m 中具有给定键的元素 |
map<string, int> word_count;
word_count.insert(map<string, int>::value_type("Anna", 1));
// 此处 "Anna" 键,已经存在,不会作任何操作
word_count.insert(make_pair("Anna", 1));
typedef map<string, int>::value_type valueType;
word_count.insert(valueType("Zhang", 2));
string word;
while(cin >> word)
{
pair<map<string, int>::iterator, bool> ret = word_count.insert(make_pair(word, 1));
// 已存在,插入失败,ret.second 为 false
if(!ret.second)
++ret.first->second;
// ret.first 类型为 map<string, int>::iterator
// 该迭代器指向 map<string, int>::value_type
}
map 中的查询操作
m.count(k)
返回 m 中 k 的出现次数,只能是0 或者 1
m.find(k)
如果 m 中存在按 k 索引的元素,则返回指向该元素的迭代器。否则,返回超出末端迭代器
map<string, int> word_count;
int occurs = 0;
// 此处实际上使用了2次查找
// 因为下标操作,总是会查找一次
if(word_count.count("fooBar"))
occurs = word_count["fooBar"];
// 此处只查找了一次
map<string, int>::iterator iter = word_count.find("fooBar2");
if(iter != word_count.end())
occurs = iter->second;
从 map 中删除元素
m.erase(k)
删除 m 中 键为 k 的元素。返回 size_type 类型,表示删除的个数。只能是0 或者 1
m.erase(p)
删除 m 中迭代器 p 所指向的元素。p 指向的元素必须存在,且不能是 m.end()。返回 void
m.erase(b, e)
删除由迭代器b 和 e 标记的范围。返回 void
map<string, int> word_count;
word_count.insert(make_pair("z", 1));
word_count.insert(make_pair("a", 2));
map<string, int>::iterator iter = word_count.begin();
while( iter!= word_count.end())
{
cout << "Key: " << iter->first << ", ";
cout << "Value: " << iter->second << endl;
++iter;
}
// 结果是:
// Key: a, Value: 2
// Key: z, Value: 1
// 说明,使用迭代器遍历 map 容器时,迭代器指向的元素按照 键的升序排列