内容主要涉及map, set, multimap和multiset四类容器。
概述
关联容器(Associative Container)与顺序容器(Sequential Container)的本质区别在于:关联容器是通过键(key)存储和读取元素的,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。
关联容器支持通过键来高效地查找和读取元素,两个基本的关联容器是map和set。map的元素是“键-值”对的二元组形式:键用作元素在map中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。set和map类型的对象所包含的元素都具有不同的键。如果需要一个键对应多个实例,则需要使用multimap或multiset类型。这两种类型允许多个元素拥有相同的键。
map |
关联数组:元素通过键来存储和读取 |
set |
大小可变的集合,支持通过键实现的快速读取 |
multimap |
支持同一个键多次出现的map类型 |
multiset |
支持同一个键多次出现的set类型 |
pair类型
pair模板类用来绑定两个对象为一个新的对象,该类型在<utility>头文件中定义。pair类型提供的操作如下表:
pair<T1, T2> p1; |
创建一个空的pair对象,它的两个元素分别是T1和T2类型,采用值初始化 |
pair<T1, T2> p1(v1, v2); |
创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2
|
make_pair(v1, v2) |
以v1和v2值创建一个新的pair对象,其元素类型分别是v1和v2的类型 |
p1 < p2 |
字典次序:如果p1.first<p2.first或者!(p2.first < p1.first)&& p1.second<p2.second,则返回true |
p1 == p2 |
如果两个pair对象的first和second成员依次相等,则这两个对象相等。 |
p.first |
返回p中名为first的(公有)数据成员 |
p.second |
返回p中名为second的(公有)数据成员 |
关联容器
关联容器共享大部分顺序容器的操作,但不提供front, push_front, back, push_back以及pop_back操作。
具体而言,有顺序容器中的:前三种构造函数;关系运算;begin, end, rbegin和rend操作;类型别名;swap和赋值操作,但关联容器不提供assign函数;clear和erase函数,但erase函数返回 void类型;关于容器大小的操作,但resize函数不能用于关联容器。
map类型
map类型定义在头文件<map>中。map是键-值对的集合,通常看作关联数组:可使用键作为下标来获取一个值。map类定义内部定义的类型有key_type, mapped_type, value_type,如下表所示:
map<K, V>::key_type |
在map容器内,用做索引的键的类型 |
map<K, V>::mapped_type |
在map容器中,键所关联的值的类型 |
map<K, V>::value_type |
map的值类型:一个pair类型,它的first元素具有 const map<K, V>::key_type类型,而second元素 则为map<K, V>::mapped_type类型
|
注意:map的元素类型为pair类型,且键成员不可修改。其它类型别名与顺序容器一样。
map对象的定义
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> |
键类型的约束
在使用关联容器时,它的键不但有一个类型,而且还有一个相关的比较函数。默认情况下,标准库使用键类型定义的 < 操作符来实现键的比较。这个比较函数必须满足:当一个键和自身比较时,结果必定是false;当两个键之间都不存在“小于”关系时,则容器将之视为相同的键。也就是说,map内的元素按键值升序排列。
operator[]
A::reference operator[](const Key& key); |
[]操作符返回键key所关联的值的引用;如果该键key不存在,则向map对象添加一个新的元素,元素的键为key,所关联的值采用值初始化。(要特别留意这个副作用)
|
注:map下标操作符返回的类型(mapped_type&)与对map迭代器进行解引用获得的类型(value_type)不相同。
例如:
map <string, int> wordCount; // empty map
word_count["Hello"] = 1;
上面的代码首先创建一个空的map对象,然后执行下列步骤:
1)在wordCount中查找键为“Hello”的元素,没有找到;
2)将一个新的键-值对插入到wordCount中,其中,键为“Hello”,值为0
3)读取新插入的键-值对的值,并将它的值赋为1。
应用实例,下面的程序用来统计一篇英文文章中单词出现的频率:
#include <iostream> #include <map> using namespace std;
int main() { map<string, int> wordCount; string word; while (cin >> word) ++wordCount[word];
for (map<string, int>::iterator it = wordCount.begin(); it != wordCount.end(); ++it) cout<<"Word: "<<(*it).first<<" /tCount: "<<(*it).second<<endl;
return 0; }
|
map::insert
m.insert(e) |
e是一个用在m上的value_type类型的值,如果键(e.first)不在m中,则插入e到m中;如果键已经在m中存在,则保持m不变。 该函数返回一个pair类型对象,如果发生了插入动作,则返回pair(it, true);否则返回pair(it, false)。其中,it是指向键为e.first那个元素的迭代器。 |
m.insert(beg, end) |
beg和end是标记元素范围的迭代器,其中的元素必须为value_type类型的键-值对。对于该范围内的所有元素,如果它的键在m中不存在,则将该键及其关联的值插入到m。返回void类型。
|
m.insert(iter, e) |
insert(e),并以iter为起点搜索新元素的位置。返回一个迭代器,指向m中键为e.first的元素。 |
注:当需要插入一个map元素时,一是可以用map::value_type来构造一个pair对象,另外,也可以用make_pair来构造这个对象。
查找元素
m.count(k) |
返回m中k的出现次数(0或1) |
m.find(k) |
如果容器中存在键为k的元素,则返回指向该元素的迭代器。 如果不存在,则返回end()值。 |
删除元素
m.erase(k) |
删除m中键为k的元素,返回size_type类型的值,表示删除的元素个数(0或1) |
m.erase(p) |
从m中删除迭代器p所指向的元素。p必须指向m中确实存在的元素,而且不能等于e.end()。返回void类型 |
m.erase(b, e) |
从m中删除[b, e)范围内的元素,返回void类型 |
set类型
set类型定义于<set>头文件中。set容器支持大部分map容器的操作,如:构造函数;insert操作;count和find操作; erase操作。两个例外情况是:set不支持下标操作符,而且没有定义mapped_type类型。与map一样,set容器存储的键也必须是唯一的,而且不能修改。
multimap和multiset类型
map和set容器中,一个键只能对应一个实例。而multiset和multimap类型则允许一个键对应多个实例。
multimap和multiset所支持的操作分别与map和set的操作相同,只有一个例外:multimap不支持下标运算。为了顺序一个键可以对应多个值这一特性,map和mulitmap,或set和multiset中相同的操作都以不同的方式做出了一定的修改。
元素的添加和删除
map和set容器中的insert和erase操作同样适用于multimap和multiset容器,实现元素的添加和删除。
由于键不要求是唯一的,因此每次调用insert总会添加一个元素。
而带有一个键参数的erase将删除拥有该键的所有元素,并返回删除元素的个数;而带有一个或一对迭代器参数的erase版本只删除指定的元素,并返回void类型。
查找元素
在map和set容器中,元素是有序存储的(升序),同样multimap和multiset也一样。因此,在multimap和multiset容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放,即迭代遍历时,可保证依次返回特定键所关联的所有元素。
要查找特定键所有相关联的值,可以有下面三种方法:
1)配合使用find和count来查找:count函数求出某键出现的次数,而find操作返回指向第一个键的实例的迭代器。
2)使用lower_bound和upper_bound函数:这两个函数常用于multimap和multiset,但也可以用于map和set容器。所有这些操作都需要传递一个键,并返回一个迭代器。
m.lower_bound(k) |
返回一个迭代器,指向键不小于k的第一个元素
|
m.upper_bound(k) |
返回一个迭代器,指向键大于k的第一个元素
|
m.equal_range(k) |
返回一个迭代器的pair对象;它的first成员等价于 m.lower_bound(k),而second成员则等价于 m.upper_bound(k) |
注意:形成的有效区间是[lower_bound(k), upper_bound(i)),是个半开半闭区间。
lower_bound返回的迭代器不一定指向拥有特定键的元素。如果该键不在容器中,则lower_bound返回在保持容器元素顺序的前提下该键应被插入的第一个位置。
若键不存在,返回的迭代器相同。
3)使用equal_range,其实质跟法2)相同。
相关推荐
### C++顺序容器、容器适配器及关联容器的操作详解 #### 一、顺序容器概述 在C++标准库中,顺序容器是一类用于存储元素的容器,它们以特定的顺序来排列元素,并且通常提供了多种操作方法。本文将详细介绍几种常见的...
本资源是使用XMind总结C++中关联容器的使用,关联容器包括map,set,multimap,multiset。内含相关的操作及构造函数,代码片段演示
关联容器是C++标准库中一类特殊的容器,它们允许通过键(key)高效地查找、插入和删除元素。本文将深入解析C++ Primer中提到的关联容器,特别是map和set的使用。 首先,关联容器包括set、map、multiset和multimap四...
C++中的关联容器是STL(Standard Template Library)的一部分,它们包括了set和map等容器。这些容器的主要特点是它们的元素不是按照它们在容器中的位置排序,而是通过一个关键字(key)来组织和访问,提供了高效的...
本资料“C++ associative containers.zip”可能包含了一些关于C++关联容器的示例代码和讲解,主要涵盖了以下知识点: 1. **unordered_set 和 set** - `std::set` 是一个红黑树实现的关联容器,它存储的是唯一元素...
顺序容器根据元素的存储和访问方式可以进一步分类为序列容器和关联容器。序列容器包括vector、list、forward_list、deque等,而关联容器则包括set、multiset、map、multimap等。 C++内置了array(数组)这一序列...
C++标准STL提供序列容器如vector、string、deque和list,以及关联容器如set、multiset、map和multimap。非标准容器包括slist(单向链表)和rope(一种重型字符串)。此外,还有哈希容器和一些非STL标准容器如数组、...
根据数据的组织形式不同,C++中的容器大致可以分为两大类:**顺序存储结构**和**关联存储结构**。 - **顺序存储结构**:这类容器按照元素插入的顺序来存储数据,主要包括`vector`、`list`、`deque`等。 - **关联...
在C++中,容器分为三类:顺序容器、关联容器和容器适配器。 顺序容器 顺序容器按照元素的顺序存储,支持随机访问。常见的顺序容器有: 1. vector:数组类模板,支持随机访问效率高,但是删除与插入效率非常低。...
在C++标准模板库(STL)中,`set`容器是一种非常重要的关联容器,主要用于存储唯一元素,并且这些元素会根据其键值自动排序。`set`内部通常采用红黑树(一种自平衡的二叉查找树)来实现,这使得它在执行插入、删除和...
C++提供了多种优化手段,如使用STL容器(如set和unordered_set)的特性,或者使用多线程(如std::thread或OpenMP)来并行处理数据。 在C++中实现关联规则需要理解数据挖掘的基本原理,同时熟练掌握C++编程技巧和库...
而`std::map`则是一个关联容器,以键值对的形式存储数据,提供了快速查找功能。 标准库是C++的重要组成部分,它包含了各种通用的工具和资源,如输入/输出流、字符串处理、算法、智能指针等。例如,`std::cin`和`std...
实验报告的主题是C++编程,涉及了关联容器(如map)和泛型算法的应用。关联容器是C++标准库中的一种容器,它能够以键值对的形式存储元素,其中map容器将唯一的键映射到相应的值。在这个实验中,学生通过实现不同的...
《C++关联容器:sparsehash实现详解》 在C++编程中,关联容器是一种非常重要的数据结构,它们允许我们高效地存储和检索键值对。其中,`sparsehash`是Google开源的一个轻量级、高性能的哈希表库,特别适合处理大量...
`std::map`则是一个关联容器,通过键值对存储元素,提供按键排序的查找。例如: ```cpp std::set<int> mySet {1, 2, 3}; mySet.insert(4); std::map, int> myMap; myMap["apple"] = 1; myMap["banana"] = 2; ``` ...
C++ primer 5th,第十一章——关联容器,笔记&思维导图 按教材整理。
STL关联容器是C++ Standard Template Library中的一类重要容器,它们主要负责通过键值(key)来存储和检索元素。关联容器与序列式容器(如vector、list、deque等)不同,后者是通过元素在容器内的位置顺序来存取元素。...
map容器是一个关联容器,它将键值对存储在一个容器中,键值对的类型可以是任何类型,包括基本类型和用户定义类型。map容器的头文件是,在使用时需要包含这个头文件。 二、定义map容器 定义map容器可以使用以下两种...
在"c++STL学习——各种容器的技术总结和用法代码实例"中,我们将深入探讨C++ STL的容器部分。 1. 容器概览: C++ STL中的容器是一些类模板,用于存储和管理元素集合。常见的容器有向量(vector)、列表(list)、...