关联容器

本文深入探讨关联容器(如map、set、multimap、multiset)和pair类型的使用方法,包括构造、操作及特性。重点阐述了如何通过键高效查找、插入、删除元素,并介绍pair类型的基本操作和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、关联容器支持通过键来高校地查找和读取元素,两个基本的关联容器类型是map和set。map的元素以键-值对的形式组织:键用作元素在map中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。

2、关联容器类型:
map                                关联数组:元素通过键来存储和读取
set                                  大小可变的集合,支持通过键实现的快速读取
multimap                       支持同一个键多次出现的map类型
multiset                          支持同一个键多次出现的set类型

3、pair类型:pair包含两个数据值,也是一种模板类型,pair对象所包含的两个数据成员各自对应的类型名字,这两个类型不必相同。
pair类型提供的操作:
pair<T1,T2>  p1;  创建一个空的pair对象,它的两个元素分别为T1和T2类型,采用值初始化
pair<T1,T2>  p1(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
p.first   返回p中名为first的(公有)数据成员
p.second  返回p的名为second的(公有)数据成员

4、关联容器不提供front、push_front、pop_front、back、push_back以及pop_back操作。关联容器元素根据键的次序排列。关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。

5、map的构造函数:
map<k,v> m;
map<k,v> m(m2);
map<k,v> m(b,e);   创建map类型的对象m,存储迭代器b和e标记的范围内所有元素的副本,元素的类型必须能转换为pair尖左括号const k,v尖右括号

6、键类型必须定义<操作符,而且该操作符应能“正确地工作”

7、map<string,int> word_count;
word_count["Anna"] = 1;
程序执行过程如下:
1)在word_count中查找键为Anna的元素,没有找到。
2)将一个新的键-值对插入到word_count中,它的键是const string类型的对象,保存Anna,而它的值则采用值初始化,这就意味着本例中值为0.
3)将这个新的键-值对插入到word_count中。
4)读取新插入的元素,并将它的值赋为1。
只有在所查找的键不存在时,map容器才为该键创建一个新的元素,并将它插入到此map对象中。

8、map容器提供的insert操作:
m.insert(e);  返回一个pair类型对象,包含指向键为e.first的元素的map迭代器,以及一个bool类型的对象,表示是否插入了该元素
m.insert(beg,end); 返回void类型
m.insert(iter,e); e是一个用在m上的value_type类型的值,如果键(e.first)不在m中,则创建新元素,并以迭代器iter为起点搜索新元素存储的位置。返回一个迭代器,指向m中具有给定键的元素

m.count(k)  返回m中k的出现次数
m.find(k)  如果m容器中存在按k索引的元素,则返回指向该元素的迭代器,如果不存在,则返回超出末端迭代器

9、从map对象中删除元素:
m.erase(k)  返回size_type类型的值,表示删除的元素个数
m.erase(p)  返回void类型
m.erase(b,e)   返回void类型

10、set容器只是单纯的键的集合。当只想知道一个值是否存在时,使用set容器最合适。set中的键为const,在获得指向set中某元素的迭代器后,只能对其做读操作,而不能做写操作。

11、multimap和multiset类型:
如果某个键对应多个实例,则这些实例在容器中将相邻存放。
返回迭代器的关联容器操作:
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)
<think>我们被要求解释C++关联容器的定义和种类。根据引用[2]和引用[3],关联容器是C++标准库中的一类容器,它们通过关键字(key)来存储和访问元素。关联容器分为有序关联容器和无序关联容器两大类。###有序关联容器有序关联容器使用比较运算符(默认是<)来组织元素,内部通常以平衡二叉搜索树(如红黑树)实现,因此元素总是按照关键字升序排列(除非自定义比较函数)。包括: -`set`:只存储关键字,关键字不可重复- `map`:存储键值对(key-value),每个key唯一- `multiset`:关键字可重复出现的set- `multimap`:关键字可重复出现的map###无序关联容器无序关联容器(引用[2])使用哈希函数和关键字类型的==运算符来组织元素。在关键字类型的元素没有明显序关系或维护序的代价高昂时,无序容器非常有用。包括: -`unordered_set`:哈希集合,关键字不可重复-`unordered_map`:哈希映射,每个key唯一(最常用,如引用[2]中的单词计数例子) -`unordered_multiset`:关键字可重复的unordered_set-`unordered_multimap`:关键字可重复的unordered_map###关联容器的关键特性1.**关键字要求**:有序容器要求关键字类型必须定义比较运算符(或提供自定义比较函数);无序容器要求关键字类型必须支持哈希函数和==运算符。2.**元素访问**:map和unordered_map支持下标操作(通过key访问value),但注意:下标操作可能会插入新元素(如果key不存在)。可以使用`at()`成员函数(引用[4])来访问元素,如果key不存在会抛出异常。 3. **元素查找**:使用`find()`成员函数查找元素,返回迭代器;`count()`返回关键字出现的次数(引用[4])。4.**范围查找**:有序关联容器支持`lower_bound()`、`upper_bound()`和`equal_range()`(引用[4]),用于在有序序列中定位元素范围。###示例代码引用[2]中的无序映射示例:```cppvoiduse_unorderd_map(){unordered_map<string,size_t> word_count;stringword;while(cin>> word) {word_count[word]++; //计数}for(constauto &word :word_count) {cout<< "key is" <<word.first<< "value is" <<word.second<< endl;} }``` 引用[3]中的嵌套关联容器示例(map的value是vector):```cppmap<string,vector<pair<string,string>>>peo; //姓:名字和生日// ...输入数据//遍历输出```###总结关联容器提供基于关键字的快速查找(对数时间复杂度或平均常数时间复杂度)。选择有序还是无序容器取决于是否需要对元素排序以及性能要求。---§§相关问题§§1.如何为自定义类型实现有序关联容器(如set)所需的比较函数? 2.无序关联容器的哈希函数如何自定义?3.关联容器的插入操作有哪些方法?它们有什么区别? 4.如何高效地遍历关联容器?</think>### C++ 关联容器详解 #### 1. 关联容器定义 关联容器是 C++ 标准库中的一类特殊容器,**通过关键字(key)而非位置索引来存储和访问元素**。与顺序容器(如 vector/list)不同,关联容器使用**高效的数据结构(通常是红黑树或哈希表)** 组织元素,实现快速查找(平均 $O(log n)$ 或 $O(1)$ 时间复杂度)[^2][^3]。 核心特征: - 元素以键值对(key-value)形式存储 - 自动维护元素有序性(有序容器)或哈希组织(无序容器) - 提供基于关键字的快速查找、插入和删除操作 #### 2. 关联容器分类 **有序关联容器**(基于红黑树实现): | 容器类型 | 特性描述 | 头文件 | |----------------|-----------------------------|-------------| | `std::set` | 唯一关键字集合 | `<set>` | | `std::map` | 唯一键值对映射 | `<map>` | | `std::multiset`| 允许重复关键字集合 | `<set>` | | `std::multimap`| 允许重复键值对映射 | `<map>` | **无序关联容器**(基于哈希表实现): | 容器类型 | 特性描述 | 头文件 | |------------------------|-----------------------------|-----------------| | `std::unordered_set` | 唯一关键字哈希集合 | `<unordered_set>` | | `std::unordered_map` | 唯一键值对哈希映射 | `<unordered_map>` | | `std::unordered_multiset`| 允许重复关键字哈希集合 | `<unordered_set>` | | `std::unordered_multimap`| 允许重复键值对哈希映射 | `<unordered_map>` | #### 3. 关键特性对比 | 特性 | 有序容器 | 无序容器 | |----------------------|-----------------------------|-----------------------------| | **底层结构** | 红黑树 | 哈希表 | | **元素顺序** | 按关键字严格排序 | 无特定顺序 | | **查找复杂度** | $O(log n)$ | 平均 $O(1)$,最坏 $O(n)$ | | **自定义排序** | 支持比较函数(如引用[1]) | 需自定义哈希函数和相等比较 | | **典型应用** | 需要有序访问的场景 | 快速查找且无需排序的场景 | #### 4. 基本操作示例 **有序 map 使用**(引用[3]): ```cpp std::map<std::string, std::vector<std::pair<std::string, std::string>>> people; // 插入元素 people["Smith"].emplace_back("John", "1990-01-01"); people["Smith"].emplace_back("Anna", "1992-05-15"); // 遍历输出 for (const auto& family : people) { std::cout << family.first << ":\n"; for (const auto& member : family.second) { std::cout << " " << member.first << ", born: " << member.second << "\n"; } } ``` **无序 map 使用**(引用[2]): ```cpp std::unordered_map<std::string, size_t> word_count; // 计数操作 word_count["apple"]++; word_count["banana"] = 5; // 范围查找(引用[4]) auto range = word_count.equal_range("apple"); if (range.first != range.second) { std::cout << "Count: " << range.first->second << "\n"; } ``` #### 5. 选择指南 - 需要 **元素有序遍历** 或 **范围查询**(如 `lower_bound()`)→ 选择有序容器[^4] - 追求 **最高查找性能** 且不关心顺序 → 选择无序容器[^2] - 处理 **重复关键字** → 选择 `multi` 版本容器 - 仅需 **检查存在性** → 选择 `set` 而非 `map` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值