type
status
date
slug
summary
tags
category
icon
password
comment
2024.11.27
给C++这个部分收尾一下,拖了太久了~主要介绍STL中容器和一些算法
一、array 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 元素访问函数3. 容量相关函数4. 修改器函数5. 非成员函数特性和注意事项使用场景二、std::vector 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 元素访问函数3. 容量相关函数4. 修改器函数5. 与 STL 算法结合使用特性和注意事项使用场景三、std::deque 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 元素访问函数3. 容量相关函数4. 修改器函数5. 与 STL 算法结合使用特性和注意事项使用场景四、std::forward_list 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 元素访问函数4. 修改器函数5. 链表操作6. 与 STL 算法结合使用特性和注意事项使用场景五、std::list 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 元素访问函数4. 修改器函数5. 链表操作6. 与 STL 算法结合使用特性和注意事项使用场景六、std::set 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 元素操作函数4. 查找操作函数5. 比较器6. 与 STL 算法结合使用特性和注意事项使用场景七、std::multiset 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 元素操作函数4. 查找操作函数5. 比较器6. 与 STL 算法结合使用特性和注意事项使用场景八、std::map 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 元素访问函数4. 修改器函数5. 查找操作函数6. 比较器7. 与 STL 算法结合使用特性和注意事项使用场景九、std::multimap 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 修改器函数4. 查找操作函数5. 比较器6. 与 STL 算法结合使用特性和注意事项使用场景十、std::unordered_set 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 修改器函数4. 查找操作函数5. 哈希相关函数6. 与 STL 算法结合使用特性和注意事项使用场景十一、std::unordered_multiset 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 修改器函数4. 查找操作函数5. 哈希相关函数6. 与 STL 算法结合使用特性和注意事项使用场景十二、std::unordered_map 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 元素访问函数4. 修改器函数5. 查找操作函数6. 哈希相关函数7. 与 STL 算法结合使用特性和注意事项使用场景十三、std::unordered_multimap 详解基本特点头文件成员函数详解1. 迭代器相关函数2. 容量相关函数3. 修改器函数4. 查找操作函数5. 哈希相关函数6. 与 STL 算法结合使用特性和注意事项使用场景十四、std::stack 详解基本特点头文件成员函数详解1. 容量相关函数2. 元素访问函数3. 修改器函数4. 不能与 STL 算法直接结合特性和注意事项使用场景十五、std::queue 详解基本特点头文件成员函数详解1. 容量相关函数2. 元素访问函数3. 修改器函数4. 与 STL 算法结合特性和注意事项使用场景十六、std::priority_queue 详解基本特点头文件成员函数详解1. 容量相关函数2. 元素访问函数3. 修改器函数4. 与 STL 算法结合自定义优先级1. 最小堆2. 自定义比较器特性和注意事项使用场景十七、总结对比说明函数支持对比表进一步说明十八、std::bitset详解头文件特点常用成员函数按位操作支持示例代码十九、std::pair详解头文件特点常用成员常用函数示例代码二十、STL中常用算法STL 中常用算法库详解1. 排序算法2. 查找算法3. 修改算法4. 数值计算算法5. 集合操作算法6. 其他通用算法
一、array
详解
std::array
是 C++ 标准模板库(STL)中的一个容器,提供了静态大小的数组封装。与传统的 C 风格数组相比,它在类型安全和功能性方面有更大的提升。基本特点
- 静态大小:
std::array
的大小在编译时确定,不能动态调整。
- 高效性:内部实现是一个 C 风格的数组,性能几乎没有额外开销。
- 接口丰富:提供了 STL 容器的统一接口,例如迭代器、容量操作、元素访问等。
- 类型安全:支持类型检查和范围检查(通过
at()
方法)。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器指向最后一个元素。
rend()
和crend()
:返回反向迭代器指向第一个元素之前的位置。
示例:
2. 元素访问函数
at(size_t pos)
:安全访问指定位置的元素,超出范围会抛出std::out_of_range
异常。
operator[]
:快速访问指定位置的元素,不检查范围。
front()
:返回第一个元素的引用。
back()
:返回最后一个元素的引用。
data()
:返回指向数组的指针,可以与 C 风格代码兼容。
示例:
3. 容量相关函数
size()
:返回数组的大小。
max_size()
:返回数组的最大大小,通常等于size()
。
empty()
:检查容器是否为空。
示例:
4. 修改器函数
fill(const T& value)
:将数组的每个元素设置为指定值。
swap(std::array& other)
:交换两个数组的内容。
示例:
5. 非成员函数
std::get<N>(array)
:访问数组中索引为N
的元素,编译期检查。
- 比较运算符:
==
,!=
,<
,>
,<=
,>=
。
示例:
特性和注意事项
- 大小固定:
std::array
的大小必须在编译时确定,因此适合静态分配的场景。
- 与传统数组的区别:
- 提供 STL 接口,方便与其他容器交互。
- 支持范围检查和标准库功能。
- 与动态容器的区别:
- 不支持动态扩展(如
std::vector
)。 - 性能更高,没有动态分配的开销。
使用场景
- 数组大小在编译时已知且不会改变的场景。
- 性能要求较高时,
std::array
提供了类似 C 风格数组的效率,但安全性更高。
- 需要与 STL 容器或算法结合使用时。
二、std::vector
详解
std::vector
是 C++ 标准模板库中最常用的动态数组容器,支持动态大小调整。与 std::array
不同,std::vector
的大小在运行时可以灵活扩展或收缩。基本特点
- 动态大小:支持自动扩展和收缩。
- 连续内存:存储在一块连续内存中,可与 C 风格数组兼容。
- 高效访问:提供常数时间复杂度的随机访问(通过下标操作符)。
- 丰富功能:支持 STL 迭代器、算法、容量管理等功能。
- 自动管理内存:容器会自动分配和释放内存,避免手动管理。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回指向最后一个元素的反向迭代器。
rend()
和crend()
:返回指向第一个元素之前的反向迭代器。
示例:
2. 元素访问函数
at(size_t pos)
:安全访问指定位置的元素,超出范围抛出异常。
operator[]
:快速访问指定位置的元素,不检查范围。
front()
:返回第一个元素的引用。
back()
:返回最后一个元素的引用。
data()
:返回指向底层数组的指针。
示例:
3. 容量相关函数
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
capacity()
:返回当前分配的存储容量。
empty()
:检查容器是否为空。
reserve(size_t n)
:预留至少n
个容量,避免频繁重新分配。
shrink_to_fit()
:释放未使用的内存,减少内存占用。
示例:
4. 修改器函数
clear()
:移除所有元素。
insert(iterator pos, value)
:在指定位置插入元素。
insert(iterator pos, count, value)
:在指定位置插入多个相同元素。
erase(iterator pos)
:删除指定位置的元素。
erase(iterator first, iterator last)
:删除指定范围的元素。
push_back(const T& value)
:在末尾添加元素。
emplace_back(args...)
:在末尾直接构造元素。
pop_back()
:移除末尾元素。
resize(size_t n)
:调整大小,自动填充新元素为默认值。
resize(size_t n, const T& value)
:调整大小,新元素填充为指定值。
swap(vector& other)
:交换两个容器的内容。
示例:
5. 与 STL 算法结合使用
由于
std::vector
提供迭代器接口,可以与 STL 算法无缝结合:特性和注意事项
- 内存管理:
std::vector
使用动态分配内存,可能会因频繁的扩展导致性能下降。提前使用reserve()
可优化。
- 线程安全性:
std::vector
不是线程安全的,需要外部同步。
- 性能:
- 随机访问时间复杂度为 。
- 插入或删除的时间复杂度通常为 ,尤其是中间位置的操作。
- 与 C 风格数组的兼容:可以通过
data()
函数获得底层数组的指针,与旧代码或 C 库交互。
使用场景
- 当需要动态调整数组大小时,
std::vector
是首选。
- 适合对随机访问性能有要求的场景。
- 常用于集合操作、排序、查找和通用数据存储。
三、std::deque
详解
std::deque
(双端队列)是 C++ 标准模板库中的动态序列容器,与 std::vector
类似,但它在两端的插入和删除操作效率更高。deque
是 “double-ended queue” 的简称。基本特点
- 双端操作高效:在两端插入或删除元素的时间复杂度为 。
- 动态大小:支持动态扩展和收缩。
- 非连续内存:不同于
std::vector
的连续存储,std::deque
由多个连续的小块内存组成。
- 高效访问:随机访问的时间复杂度为 ,但比
std::vector
稍慢。
- 灵活性:适合频繁在两端插入或删除元素的场景。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器,指向最后一个元素。
rend()
和crend()
:返回反向迭代器,指向第一个元素之前的位置。
示例:
2. 元素访问函数
at(size_t pos)
:安全访问指定位置的元素,超出范围会抛出异常。
operator[]
:快速访问指定位置的元素,不检查范围。
front()
:返回第一个元素的引用。
back()
:返回最后一个元素的引用。
示例:
3. 容量相关函数
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
empty()
:检查容器是否为空。
shrink_to_fit()
:调整容量,减少内存浪费(实现可能无效,依赖具体标准库)。
示例:
4. 修改器函数
clear()
:移除所有元素。
insert(iterator pos, value)
:在指定位置插入元素。
insert(iterator pos, count, value)
:在指定位置插入多个相同元素。
erase(iterator pos)
:删除指定位置的元素。
erase(iterator first, iterator last)
:删除指定范围的元素。
push_back(const T& value)
:在末尾添加元素。
push_front(const T& value)
:在开头添加元素。
emplace_back(args...)
:在末尾直接构造元素。
emplace_front(args...)
:在开头直接构造元素。
pop_back()
:移除末尾元素。
pop_front()
:移除开头元素。
resize(size_t n)
:调整大小,自动填充新元素为默认值。
resize(size_t n, const T& value)
:调整大小,新元素填充为指定值。
swap(deque& other)
:交换两个容器的内容。
示例:
5. 与 STL 算法结合使用
由于
std::deque
提供迭代器接口,可以与 STL 算法无缝结合:特性和注意事项
- 与
std::vector
的区别: std::deque
支持高效的双端操作,适合频繁在两端插入或删除元素的场景。std::vector
在末尾插入和删除时效率更高。std::vector
使用连续内存,适合与低级 C 风格代码兼容;std::deque
使用分块存储。
- 性能:
- 随机访问时间复杂度为 ,但通常比
std::vector
略慢。 - 两端插入或删除操作时间复杂度为 。
- 与 C 风格数组的兼容性:
std::deque
不支持直接返回底层数组指针(因为其内存分块实现)。
使用场景
- 当需要频繁在两端插入或删除元素时,例如队列、缓冲区。
- 随机访问要求不高,但需要灵活扩展容量的场景。
- 更高效的双端操作要求。
四、std::forward_list
详解
std::forward_list
是 C++ 标准模板库中的单向链表容器,提供了一种轻量级的数据结构。与 std::list
不同,它仅支持单向链接,内存开销较低,适合某些特定场景。基本特点
- 单向链表:每个节点只存储一个指向下一个节点的指针。
- 高效插入和删除:在链表头部或已知位置后的插入与删除操作时间复杂度为 。
- 轻量级:由于单向链接的特性,相较于双向链表 (
std::list
),内存开销更小。
- 不支持随机访问:不能通过索引访问元素,必须使用迭代器进行遍历。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 元素访问函数
std::forward_list
由于是单向链表,不支持直接的随机访问,也没有 at()
或 operator[]
等操作,需通过迭代器访问。示例:
4. 修改器函数
clear()
:移除所有元素。
insert_after(iterator pos, value)
:在指定位置之后插入一个元素。
insert_after(iterator pos, count, value)
:在指定位置之后插入多个相同元素。
erase_after(iterator pos)
:删除指定位置之后的单个元素。
erase_after(iterator first, iterator last)
:删除指定范围的元素。
push_front(const T& value)
:在链表头部插入一个元素。
emplace_front(args...)
:在链表头部直接构造元素。
pop_front()
:移除链表头部的元素。
resize(size_t n)
:调整大小,自动填充新元素为默认值。
resize(size_t n, const T& value)
:调整大小,新元素填充为指定值。
swap(forward_list& other)
:交换两个链表的内容。
示例:
5. 链表操作
merge(forward_list& other)
:合并两个有序链表,other
变为空。
remove(const T& value)
:删除所有等于指定值的元素。
remove_if(predicate)
:删除满足条件的所有元素。
reverse()
:反转链表中的元素顺序。
sort()
:对链表中的元素排序。
unique()
:移除相邻的重复元素。
示例:
6. 与 STL 算法结合使用
std::forward_list
支持与部分 STL 算法结合,但由于其单向迭代特性,不支持随机访问相关算法:特性和注意事项
- 单向链表特性:
- 插入和删除操作比
std::vector
或std::deque
更高效。 - 不支持随机访问,所有访问操作都需要通过迭代器完成。
- 与
std::list
的区别: std::forward_list
是单向链表,内存占用更少。std::list
是双向链表,支持从任意位置的高效插入和删除。
- 性能:
- 插入或删除时间复杂度为 ,适用于频繁动态修改的场景。
- 遍历或查找时间复杂度为 ,不适合需要频繁随机访问的场景。
使用场景
- 适合需要高效头部插入或删除元素的场景。
- 适合内存受限但仍需链表特性的应用(例如嵌入式开发)。
- 适用于对链表操作有需求但不需要双向链表特性的场景。
五、std::list
详解
std::list
是 C++ 标准模板库中的双向链表容器。与 std::forward_list
不同,std::list
提供了双向链接的功能,允许从任意位置进行高效插入和删除操作。基本特点
- 双向链表:每个节点存储前驱和后继的指针,可以从任意位置向前或向后遍历。
- 高效的插入和删除:在任意位置插入或删除元素的时间复杂度为 。
- 动态大小:支持动态扩展和收缩。
- 不支持随机访问:不能通过索引访问元素,必须使用迭代器进行遍历。
- 内存占用较高:由于双向链接的特性,每个节点比
std::forward_list
需要更多的内存。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器,指向最后一个元素。
rend()
和crend()
:返回反向迭代器,指向第一个元素之前的位置。
示例:
2. 容量相关函数
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
empty()
:检查容器是否为空。
示例:
3. 元素访问函数
front()
:返回第一个元素的引用。
back()
:返回最后一个元素的引用。
示例:
4. 修改器函数
clear()
:移除所有元素。
insert(iterator pos, value)
:在指定位置插入元素。
insert(iterator pos, count, value)
:在指定位置插入多个相同元素。
erase(iterator pos)
:删除指定位置的元素。
erase(iterator first, iterator last)
:删除指定范围的元素。
push_back(const T& value)
:在链表末尾插入元素。
push_front(const T& value)
:在链表头部插入元素。
emplace_back(args...)
:在链表末尾直接构造元素。
emplace_front(args...)
:在链表头部直接构造元素。
pop_back()
:移除链表末尾的元素。
pop_front()
:移除链表头部的元素。
resize(size_t n)
:调整大小,自动填充新元素为默认值。
resize(size_t n, const T& value)
:调整大小,新元素填充为指定值。
swap(list& other)
:交换两个链表的内容。
示例:
5. 链表操作
merge(list& other)
:合并两个有序链表,other
变为空。
remove(const T& value)
:删除所有等于指定值的元素。
remove_if(predicate)
:删除满足条件的所有元素。
reverse()
:反转链表中的元素顺序。
sort()
:对链表中的元素排序。
unique()
:移除相邻的重复元素。
示例:
6. 与 STL 算法结合使用
std::list
支持与 STL 算法结合,但由于其链表特性,某些算法可能效率较低:特性和注意事项
- 双向链表特性:
- 插入和删除操作比
std::vector
或std::deque
更高效,尤其是在中间位置。 - 支持双向遍历,适合需要从两端或中间插入删除的场景。
- 与
std::vector
的区别: std::list
插入和删除效率高,但随机访问效率低。std::vector
随机访问效率高,但在中间插入和删除效率低。
- 与
std::forward_list
的区别: std::list
是双向链表,支持从后向前遍历。std::forward_list
是单向链表,更轻量级,但操作有限。
使用场景
- 当需要频繁在中间插入或删除元素时,
std::list
是首选。
- 适合需要从两端进行操作且随机访问要求较低的场景。
- 在需要高效排序、合并或反转链表时。
六、std::set
详解
std::set
是 C++ 标准模板库中的有序容器,基于红黑树实现,提供高效的元素管理和有序存储。std::set
中的元素是唯一的,自动按顺序排列。基本特点
- 元素唯一性:
std::set
不允许重复元素。
- 自动排序:元素按特定的比较规则(默认升序)自动排序。
- 底层实现:基于红黑树,保证常数的插入、删除和查找时间复杂度为 。
- 不可直接修改元素值:由于元素位置依赖排序规则,必须先删除旧元素,再插入新值。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器,指向最后一个元素。
rend()
和crend()
:返回反向迭代器,指向第一个元素之前的位置。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 元素操作函数
insert(const T& value)
:插入元素,返回迭代器和布尔值,布尔值指示是否成功插入。
emplace(args...)
:在容器中直接构造元素。
erase(iterator pos)
:删除指定位置的元素。
erase(const T& value)
:删除指定值的元素,返回删除的元素个数。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(set& other)
:交换两个集合的内容。
示例:
4. 查找操作函数
find(const T& value)
:查找指定值的元素,返回迭代器,若未找到则返回end()
。
count(const T& value)
:返回指定值的出现次数(对于std::set
,结果始终为 0 或 1)。
lower_bound(const T& value)
:返回指向第一个不小于value
的迭代器。
upper_bound(const T& value)
:返回指向第一个大于value
的迭代器。
equal_range(const T& value)
:返回等于value
的元素范围(pair<iterator, iterator>
)。
示例:
5. 比较器
key_comp()
:返回用于比较键的比较器对象。
value_comp()
:返回用于比较值的比较器对象。
示例:
6. 与 STL 算法结合使用
std::set
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 唯一性:
- 插入重复元素时,
insert()
会返回插入失败的状态。
- 有序性:
- 默认按升序排列,可通过自定义比较器改变排序规则。
- 效率:
- 查找、插入、删除操作的时间复杂度为 。
- 不支持随机访问。
- 迭代器稳定性:
- 插入和删除操作不会使其他迭代器失效。
使用场景
- 需要保持元素唯一性并保持有序的场景。
- 需要高效查找、插入和删除操作时。
- 适合需要自动排序但无随机访问需求的集合操作。
七、std::multiset
详解
std::multiset
是 C++ 标准模板库中的有序容器,与 std::set
类似,但它允许重复元素。std::multiset
同样基于红黑树实现,提供高效的元素管理和有序存储。基本特点
- 允许重复元素:与
std::set
不同,std::multiset
允许存储重复的值。
- 自动排序:元素按特定的比较规则(默认升序)自动排序。
- 底层实现:基于红黑树,保证常数的插入、删除和查找时间复杂度为 。
- 只读元素:元素值不可直接修改,需通过删除再插入实现。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器,指向最后一个元素。
rend()
和crend()
:返回反向迭代器,指向第一个元素之前的位置。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 元素操作函数
insert(const T& value)
:插入元素,返回指向新插入元素的迭代器。
emplace(args...)
:在容器中直接构造元素。
erase(iterator pos)
:删除指定位置的元素。
erase(const T& value)
:删除所有与值匹配的元素,返回删除的元素个数。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(multiset& other)
:交换两个集合的内容。
示例:
4. 查找操作函数
find(const T& value)
:查找指定值的第一个元素,返回迭代器,若未找到则返回end()
。
count(const T& value)
:返回指定值的出现次数。
lower_bound(const T& value)
:返回指向第一个不小于value
的迭代器。
upper_bound(const T& value)
:返回指向第一个大于value
的迭代器。
equal_range(const T& value)
:返回等于value
的元素范围(pair<iterator, iterator>
)。
示例:
5. 比较器
key_comp()
:返回用于比较键的比较器对象。
value_comp()
:返回用于比较值的比较器对象。
示例:
6. 与 STL 算法结合使用
std::multiset
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 允许重复性:
std::multiset
允许多个相同的元素。- 插入时,所有重复元素都会按顺序排列。
- 有序性:
- 默认按升序排列,可通过自定义比较器改变排序规则。
- 效率:
- 查找、插入、删除操作的时间复杂度为 。
- 不支持随机访问。
- 迭代器稳定性:
- 插入和删除操作不会使其他迭代器失效。
使用场景
- 需要存储重复元素并保持有序的场景。
- 高效的插入、删除和查找操作。
- 适用于计数问题(例如多次出现的元素)。
八、std::map
详解
std::map
是 C++ 标准模板库中的有序关联容器,它以键值对 (key-value
) 的形式存储数据,键是唯一的,自动按顺序排列。底层实现是红黑树,提供高效的查找、插入和删除操作。基本特点
- 键唯一性:
std::map
不允许重复的键。
- 自动排序:键按照特定的比较规则(默认升序)自动排序。
- 键值对存储:每个元素是一个
std::pair
,其中first
是键,second
是值。
- 高效操作:基于红黑树实现,插入、删除和查找的时间复杂度为 。
- 动态大小:容器大小可以动态调整。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器,指向最后一个元素。
rend()
和crend()
:返回反向迭代器,指向第一个元素之前的位置。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 元素访问函数
operator[]
:通过键访问或插入元素。如果键不存在,会插入一个默认值。
at(const Key& key)
:通过键安全访问元素,若键不存在则抛出std::out_of_range
异常。
示例:
4. 修改器函数
insert(const pair<Key, T>& value)
:插入键值对,返回插入结果(成功或失败)。
insert_or_assign(key, value)
:插入或更新键值对。
emplace(args...)
:直接构造键值对。
erase(iterator pos)
:删除指定位置的元素。
erase(const Key& key)
:删除指定键的元素。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(map& other)
:交换两个容器的内容。
示例:
5. 查找操作函数
find(const Key& key)
:查找指定键的元素,返回指向该元素的迭代器,若未找到则返回end()
。
count(const Key& key)
:返回指定键的出现次数(对于std::map
,结果始终为 0 或 1)。
lower_bound(const Key& key)
:返回指向第一个不小于key
的迭代器。
upper_bound(const Key& key)
:返回指向第一个大于key
的迭代器。
equal_range(const Key& key)
:返回等于key
的元素范围(pair<iterator, iterator>
)。
示例:
6. 比较器
key_comp()
:返回用于比较键的比较器对象。
value_comp()
:返回用于比较值的比较器对象。
示例:
7. 与 STL 算法结合使用
std::map
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 键唯一性:
- 若插入重复键,
insert()
操作会失败。 - 若需要存储重复键,使用
std::multimap
。
- 有序性:
- 默认按键升序排列,可通过自定义比较器改变排序规则。
- 效率:
- 插入、删除和查找操作的时间复杂度为 。
- 不支持随机访问。
- 迭代器稳定性:
- 插入和删除操作不会使其他迭代器失效,但指向已删除元素的迭代器失效。
使用场景
- 需要通过唯一键快速访问关联值的场景。
- 当需要有序存储键值对并高效进行查找、插入或删除时。
- 当键值对需要保持按顺序排列时。
九、std::multimap
详解
std::multimap
是 C++ 标准模板库中的有序关联容器,与 std::map
类似,但它允许一个键对应多个值。std::multimap
基于红黑树实现,提供高效的查找、插入和删除操作。基本特点
- 键不唯一:允许存储多个具有相同键的键值对。
- 自动排序:键按照特定的比较规则(默认升序)自动排序。
- 键值对存储:每个元素是一个
std::pair
,其中first
是键,second
是值。
- 高效操作:插入、删除和查找的时间复杂度为 。
- 动态大小:容器大小可以动态调整。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
rbegin()
和crbegin()
:返回反向迭代器,指向最后一个元素。
rend()
和crend()
:返回反向迭代器,指向第一个元素之前的位置。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 修改器函数
insert(const pair<Key, T>& value)
:插入键值对。
emplace(args...)
:直接构造键值对。
erase(iterator pos)
:删除指定位置的元素。
erase(const Key& key)
:删除所有与键匹配的元素,返回删除的元素个数。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(multimap& other)
:交换两个容器的内容。
示例:
4. 查找操作函数
find(const Key& key)
:查找指定键的第一个元素,返回迭代器,若未找到则返回end()
。
count(const Key& key)
:返回指定键的出现次数。
lower_bound(const Key& key)
:返回指向第一个不小于key
的迭代器。
upper_bound(const Key& key)
:返回指向第一个大于key
的迭代器。
equal_range(const Key& key)
:返回与key
匹配的元素范围(pair<iterator, iterator>
)。
示例:
5. 比较器
key_comp()
:返回用于比较键的比较器对象。
value_comp()
:返回用于比较值的比较器对象。
示例:
6. 与 STL 算法结合使用
std::multimap
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 键允许重复:
- 与
std::map
的主要区别是std::multimap
允许多个相同的键。
- 有序性:
- 默认按键升序排列,可通过自定义比较器改变排序规则。
- 效率:
- 插入、删除和查找操作的时间复杂度为 。
- 不支持随机访问。
- 迭代器稳定性:
- 插入和删除操作不会使其他迭代器失效,但指向已删除元素的迭代器失效。
使用场景
- 需要存储重复键并保持有序的场景。
- 当键值对需要按顺序排列但允许多个键时。
- 用于高效查找特定键的所有匹配值的应用。
十、std::unordered_set
详解
std::unordered_set
是 C++ 标准模板库中的无序容器,用于存储唯一元素,底层实现基于哈希表(hash table)。它提供了高效的插入、删除和查找操作,但元素没有特定顺序。基本特点
- 元素唯一性:
std::unordered_set
不允许重复的元素。
- 无序存储:元素存储顺序与插入顺序或键值大小无关。
- 底层实现:基于哈希表,通过哈希函数快速定位元素。
- 高效操作:插入、删除和查找的平均时间复杂度为 (最坏情况下为 )。
- 动态大小:容器大小可以动态调整。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 修改器函数
insert(const T& value)
:插入元素,返回插入结果(成功或失败)。
emplace(args...)
:直接构造元素。
erase(iterator pos)
:删除指定位置的元素。
erase(const T& value)
:删除指定值的元素,返回删除的元素个数。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(unordered_set& other)
:交换两个容器的内容。
示例:
4. 查找操作函数
find(const T& value)
:查找指定值的元素,返回迭代器,若未找到则返回end()
。
count(const T& value)
:返回指定值的出现次数(对于std::unordered_set
,结果始终为 0 或 1)。
示例:
5. 哈希相关函数
bucket_count()
:返回当前桶的数量。
bucket_size(size_t n)
:返回指定桶中元素的数量。
bucket(const T& value)
:返回元素所在的桶的编号。
load_factor()
:返回当前负载因子(元素数量 / 桶数量)。
max_load_factor()
:返回或设置允许的最大负载因子。
rehash(size_t n)
:重置桶数量,保证至少有n
个桶。
reserve(size_t n)
:调整容器的容量以容纳n
个元素,减少重哈希的次数。
示例:
6. 与 STL 算法结合使用
std::unordered_set
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 唯一性:
std::unordered_set
中元素必须唯一,插入重复元素会被忽略。
- 无序性:
- 元素存储顺序由哈希表决定,与插入顺序无关。
- 效率:
- 插入、删除和查找的平均时间复杂度为 ,但最坏情况下为 (当发生哈希冲突时)。
- 迭代器稳定性:
- 插入和删除操作可能导致迭代器失效。
使用场景
- 当需要唯一元素集合但不需要有序存储时。
- 需要快速插入、删除和查找操作的场景。
- 使用哈希表的场景,适合需要高效管理大量数据的应用。
十一、std::unordered_multiset
详解
std::unordered_multiset
是 C++ 标准模板库中的无序关联容器,用于存储非唯一元素。与 std::unordered_set
类似,它底层实现基于哈希表,但允许重复的元素。基本特点
- 允许重复元素:与
std::unordered_set
不同,std::unordered_multiset
允许存储多个相同的值。
- 无序存储:元素存储顺序与插入顺序或键值大小无关。
- 底层实现:基于哈希表,通过哈希函数快速定位元素。
- 高效操作:插入、删除和查找的平均时间复杂度为 (最坏情况下为 )。
- 动态大小:容器大小可以动态调整。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 修改器函数
insert(const T& value)
:插入元素。
emplace(args...)
:直接构造元素。
erase(iterator pos)
:删除指定位置的元素。
erase(const T& value)
:删除所有与值匹配的元素,返回删除的元素个数。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(unordered_multiset& other)
:交换两个容器的内容。
示例:
4. 查找操作函数
find(const T& value)
:查找指定值的元素,返回迭代器,若未找到则返回end()
。
count(const T& value)
:返回指定值的出现次数。
equal_range(const T& value)
:返回与value
匹配的元素范围(pair<iterator, iterator>
)。
示例:
5. 哈希相关函数
bucket_count()
:返回当前桶的数量。
bucket_size(size_t n)
:返回指定桶中元素的数量。
bucket(const T& value)
:返回元素所在的桶的编号。
load_factor()
:返回当前负载因子(元素数量 / 桶数量)。
max_load_factor()
:返回或设置允许的最大负载因子。
rehash(size_t n)
:重置桶数量,保证至少有n
个桶。
reserve(size_t n)
:调整容器的容量以容纳n
个元素,减少重哈希的次数。
示例:
6. 与 STL 算法结合使用
std::unordered_multiset
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 允许重复性:
- 与
std::unordered_set
的主要区别是std::unordered_multiset
允许重复的元素。
- 无序性:
- 元素存储顺序由哈希表决定,与插入顺序无关。
- 效率:
- 插入、删除和查找的平均时间复杂度为 ,但最坏情况下为 (当发生哈希冲突时)。
- 迭代器稳定性:
- 插入和删除操作可能导致迭代器失效。
使用场景
- 当需要无序存储但允许重复元素的集合时。
- 需要高效插入、删除和查找操作的场景。
- 使用哈希表实现的场景,适合管理大量可能重复的数据。
十二、std::unordered_map
详解
std::unordered_map
是 C++ 标准模板库中的无序关联容器,用于存储键值对 (key-value
) 数据。它底层实现基于哈希表,提供高效的查找、插入和删除操作。基本特点
- 键唯一性:
std::unordered_map
中的键是唯一的,重复键的插入操作会失败。
- 无序存储:键值对的存储顺序与插入顺序或键值大小无关。
- 底层实现:基于哈希表,通过哈希函数快速定位元素。
- 高效操作:插入、删除和查找的平均时间复杂度为 (最坏情况下为 )。
- 动态大小:容器大小可以动态调整。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 元素访问函数
operator[]
:通过键访问或插入元素。如果键不存在,会插入一个默认值。
at(const Key& key)
:通过键安全访问元素,若键不存在则抛出std::out_of_range
异常。
示例:
4. 修改器函数
insert(const pair<Key, T>& value)
:插入键值对,返回插入结果(成功或失败)。
insert_or_assign(key, value)
:插入或更新键值对。
emplace(args...)
:直接构造键值对。
erase(iterator pos)
:删除指定位置的元素。
erase(const Key& key)
:删除指定键的元素。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(unordered_map& other)
:交换两个容器的内容。
示例:
5. 查找操作函数
find(const Key& key)
:查找指定键的元素,返回迭代器,若未找到则返回end()
。
count(const Key& key)
:返回指定键的出现次数(对于std::unordered_map
,结果始终为 0 或 1)。
示例:
6. 哈希相关函数
bucket_count()
:返回当前桶的数量。
bucket_size(size_t n)
:返回指定桶中元素的数量。
bucket(const Key& key)
:返回键对应的桶编号。
load_factor()
:返回当前负载因子(元素数量 / 桶数量)。
max_load_factor()
:返回或设置允许的最大负载因子。
rehash(size_t n)
:重置桶数量,保证至少有n
个桶。
reserve(size_t n)
:调整容器的容量以容纳n
个元素,减少重哈希的次数。
示例:
7. 与 STL 算法结合使用
std::unordered_map
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 键唯一性:
std::unordered_map
中的键必须唯一,插入重复键会失败。
- 无序性:
- 元素存储顺序由哈希表决定,与插入顺序无关。
- 效率:
- 插入、删除和查找的平均时间复杂度为 ,但最坏情况下为 (当发生哈希冲突时)。
- 迭代器稳定性:
- 插入和删除操作可能导致迭代器失效。
使用场景
- 需要通过唯一键快速访问关联值的场景。
- 当不需要有序存储键值对时。
- 使用哈希表的高效键值映射管理场景。
十三、std::unordered_multimap
详解
std::unordered_multimap
是 C++ 标准模板库中的无序关联容器,用于存储键值对 (key-value
) 数据。与 std::unordered_map
不同,它允许一个键对应多个值,底层实现基于哈希表。基本特点
- 键允许重复:与
std::unordered_map
不同,std::unordered_multimap
允许一个键存储多个值。
- 无序存储:键值对的存储顺序与插入顺序或键值大小无关。
- 底层实现:基于哈希表,通过哈希函数快速定位元素。
- 高效操作:插入、删除和查找的平均时间复杂度为 (最坏情况下为 )。
- 动态大小:容器大小可以动态调整。
头文件
声明和初始化
成员函数详解
1. 迭代器相关函数
begin()
和cbegin()
:返回指向第一个元素的迭代器或常量迭代器。
end()
和cend()
:返回指向末尾后一个位置的迭代器或常量迭代器。
示例:
2. 容量相关函数
empty()
:检查容器是否为空。
size()
:返回当前元素个数。
max_size()
:返回容器支持的最大元素数量。
示例:
3. 修改器函数
insert(const pair<Key, T>& value)
:插入键值对。
emplace(args...)
:直接构造键值对。
erase(iterator pos)
:删除指定位置的元素。
erase(const Key& key)
:删除所有与键匹配的元素,返回删除的元素个数。
erase(iterator first, iterator last)
:删除指定范围内的元素。
clear()
:移除所有元素。
swap(unordered_multimap& other)
:交换两个容器的内容。
示例:
4. 查找操作函数
find(const Key& key)
:查找指定键的第一个元素,返回迭代器,若未找到则返回end()
。
count(const Key& key)
:返回指定键的出现次数。
equal_range(const Key& key)
:返回与key
匹配的元素范围(pair<iterator, iterator>
)。
示例:
5. 哈希相关函数
bucket_count()
:返回当前桶的数量。
bucket_size(size_t n)
:返回指定桶中元素的数量。
bucket(const Key& key)
:返回键对应的桶编号。
load_factor()
:返回当前负载因子(元素数量 / 桶数量)。
max_load_factor()
:返回或设置允许的最大负载因子。
rehash(size_t n)
:重置桶数量,保证至少有n
个桶。
reserve(size_t n)
:调整容器的容量以容纳n
个元素,减少重哈希的次数。
示例:
6. 与 STL 算法结合使用
std::unordered_multimap
提供了迭代器接口,可以与 STL 算法结合:特性和注意事项
- 键允许重复:
- 与
std::unordered_map
的主要区别是std::unordered_multimap
允许重复的键。
- 无序性:
- 键值对存储顺序由哈希表决定,与插入顺序无关。
- 效率:
- 插入、删除和查找的平均时间复杂度为 ,但最坏情况下为 (当发生哈希冲突时)。
- 迭代器稳定性:
- 插入和删除操作可能导致迭代器失效。
使用场景
- 需要无序存储并允许重复键的关联数据场景。
- 需要快速插入、删除和查找操作的场景。
- 适用于管理大量数据,且对键值对存储顺序无要求的场景。
十四、std::stack
详解
std::stack
是 C++ 标准模板库中的适配器容器,用于实现“后进先出”(LIFO,Last In First Out)的栈数据结构。std::stack
并不是一个独立的容器,而是通过封装其他序列容器(默认是 std::deque
)实现的。基本特点
- 后进先出:栈的操作遵循 LIFO 原则。
- 容器适配器:
std::stack
基于底层容器实现,支持std::deque
(默认)、std::vector
或std::list
。
- 高效操作:提供常数时间复杂度的插入和删除操作。
- 动态大小:底层容器可以动态调整大小。
头文件
声明与初始化
成员函数详解
1. 容量相关函数
empty()
:检查栈是否为空。
size()
:返回栈中元素的个数。
示例:
2. 元素访问函数
top()
:返回栈顶元素的引用。
示例:
3. 修改器函数
push(const T& value)
:将元素压入栈顶。
emplace(args...)
:在栈顶直接构造元素。
pop()
:移除栈顶元素。
swap(stack& other)
:交换两个栈的内容。
示例:
4. 不能与 STL 算法直接结合
由于
std::stack
不提供迭代器接口,因此不能直接与 STL 算法结合。如果需要算法支持,应直接操作底层容器。特性和注意事项
- 底层容器:
- 默认使用
std::deque
作为底层容器。 - 可以指定其他支持
push_back
、pop_back
、back
的容器,如std::vector
和std::list
。
- 只能访问栈顶元素:
std::stack
不提供对底层容器的直接访问。- 若需要遍历或随机访问,应使用底层容器。
使用场景
- 当需要模拟 LIFO 数据结构时。
- 用于递归的替代方案,例如深度优先搜索(DFS)。
- 实现回溯算法(如括号匹配、路径回溯等)。
十五、std::queue
详解
std::queue
是 C++ 标准模板库中的适配器容器,用于实现“先进先出”(FIFO,First In First Out)的队列数据结构。它通过封装其他序列容器(默认是 std::deque
)实现。基本特点
- 先进先出:队列的操作遵循 FIFO 原则。
- 容器适配器:
std::queue
基于底层容器实现,支持std::deque
(默认)或std::list
。
- 高效操作:提供常数时间复杂度的插入和删除操作。
- 动态大小:底层容器可以动态调整大小。
头文件
声明与初始化
成员函数详解
1. 容量相关函数
empty()
:检查队列是否为空。
size()
:返回队列中元素的个数。
示例:
2. 元素访问函数
front()
:返回队列中第一个元素的引用。
back()
:返回队列中最后一个元素的引用。
示例:
3. 修改器函数
push(const T& value)
:将元素添加到队列尾部。
emplace(args...)
:在队列尾部直接构造元素。
pop()
:移除队列首元素。
swap(queue& other)
:交换两个队列的内容。
示例:
4. 与 STL 算法结合
由于
std::queue
不提供迭代器接口,因此不能直接与 STL 算法结合。如果需要算法支持,应直接操作底层容器。特性和注意事项
- 底层容器:
- 默认使用
std::deque
作为底层容器。 - 可以指定其他支持
push_back
、pop_front
、front
和back
的容器,如std::list
。
- 只能访问队首和队尾元素:
std::queue
不提供对底层容器的直接访问。- 若需要遍历或随机访问,应使用底层容器。
使用场景
- 模拟 FIFO 数据结构的场景,例如任务调度、消息队列。
- 用于广度优先搜索(BFS)等算法。
- 用于生产者-消费者模型。
十六、std::priority_queue
详解
std::priority_queue
是 C++ 标准模板库中的容器适配器,用于实现优先队列。优先队列是一种特殊的队列,其中元素按照优先级顺序排列,优先级最高的元素总是位于队首。基本特点
- 优先级队列:元素以优先级顺序存储,默认是最大堆(即优先级最高的元素位于队首)。
- 容器适配器:
std::priority_queue
基于底层容器实现,通常使用std::vector
(默认)或std::deque
。
- 动态大小:底层容器可以动态调整大小。
- 底层实现:基于堆结构(默认最大堆),元素按照堆排序规则排列。
头文件
声明与初始化
成员函数详解
1. 容量相关函数
empty()
:检查优先队列是否为空。
size()
:返回优先队列中元素的个数。
示例:
2. 元素访问函数
top()
:返回优先队列中优先级最高的元素。
示例:
3. 修改器函数
push(const T& value)
:将元素添加到优先队列。
emplace(args...)
:在优先队列中直接构造元素。
pop()
:移除优先队列中优先级最高的元素。
示例:
4. 与 STL 算法结合
std::priority_queue
不直接支持迭代器,因此无法与 STL 算法直接结合。但可以通过底层容器操作堆。示例:使用
std::make_heap
操作底层容器:自定义优先级
1. 最小堆
默认情况下,
std::priority_queue
是最大堆。如果需要最小堆,可以使用 std::greater<T>
作为比较器。示例:
2. 自定义比较器
可以通过自定义函数对象或函数指针定义优先级规则。
示例:
特性和注意事项
- 默认最大堆:
- 默认情况下,
std::priority_queue
是最大堆,即优先级最高的元素位于队首。
- 底层容器:
- 默认使用
std::vector
作为底层容器。 - 可以指定其他支持随机访问的容器(如
std::deque
)。
- 只能访问队首元素:
- 无法遍历或随机访问其他元素,若需要完整数据操作,应操作底层容器。
使用场景
- 任务调度:优先处理高优先级任务。
- 数据流处理:快速找出最大或最小元素。
- 实现复杂算法:如 Dijkstra 最短路径、Prim 最小生成树。
十七、总结
以下是关于 顺序容器、关联容器、无序关联容器 和 容器适配器 的全面对比表格:
类别 | 容器 | 头文件 | 特性 |
顺序容器 | array | <array> | 固定大小的静态数组,提供 STL 接口,编译时确定大小。 |
ㅤ | vector | <vector> | 动态数组,支持快速随机访问,尾部插入和删除效率高。 |
ㅤ | deque | <deque> | 双端队列,支持两端高效插入和删除,随机访问稍慢于 vector 。 |
ㅤ | forward_list | <forward_list> | 单向链表,轻量级,适合头部插入和删除,不支持随机访问。 |
ㅤ | list | <list> | 双向链表,支持快速任意位置插入和删除,遍历性能较低,不支持随机访问。 |
关联容器 | set | <set> | 有序集合,元素唯一,自动按升序排列,基于红黑树实现。 |
ㅤ | multiset | <set> | 有序多重集合,允许重复元素,自动按升序排列,基于红黑树实现。 |
ㅤ | map | <map> | 有序键值对集合,键唯一,自动按升序排列,基于红黑树实现。 |
ㅤ | multimap | <map> | 有序键值对集合,允许重复键,自动按升序排列,基于红黑树实现。 |
无序关联容器 | unordered_set | <unordered_set> | 无序集合,元素唯一,基于哈希表实现,查找、插入和删除效率高。 |
ㅤ | unordered_multiset | <unordered_set> | 无序多重集合,允许重复元素,基于哈希表实现,查找、插入和删除效率高。 |
ㅤ | unordered_map | <unordered_map> | 无序键值对集合,键唯一,基于哈希表实现,查找、插入和删除效率高。 |
ㅤ | unordered_multimap | <unordered_map> | 无序键值对集合,允许重复键,基于哈希表实现,查找、插入和删除效率高。 |
容器适配器 | stack | <stack> | 后进先出(LIFO)栈,基于 deque 或其他序列容器实现。 |
ㅤ | queue | <queue> | 先进先出(FIFO)队列,基于 deque 或其他序列容器实现。 |
ㅤ | priority_queue | <queue> | 优先级队列,默认最大堆,基于 vector 容器实现。 |
对比说明
- 顺序容器:
- 提供连续或链式存储,适合顺序数据操作。
- 以动态数组(如
vector
)和链表(如list
)为代表,支持插入、删除和遍历操作。
- 关联容器:
- 提供键值对或唯一元素集合,元素有序存储。
- 以
map
和set
为代表,基于红黑树实现,查找效率为 。
- 无序关联容器:
- 提供无序存储,适合需要高效查找和插入的场景。
- 以哈希表为底层实现,查找效率平均为 ,最坏为 。
- 容器适配器:
- 封装底层容器,提供特定的数据结构功能。
- 以
stack
和queue
为代表,限制了操作接口以实现特定行为。
函数支持对比表
功能分类 | 支持的函数 | 顺序容器 | 关联容器 | 无序关联容器 | 容器适配器 |
构造与销毁 | 构造函数 | ✅ array ,vector ,deque ,list | ✅ set ,map ,multiset ,multimap | ✅ unordered_set ,unordered_map ,
unordered_multiset,unordered_multimap | ✅ stack ,queue ,priority_queue |
ㅤ | 析构函数 | ✅ | ✅ | ✅ | ✅ |
ㅤ | operator= | ✅ | ✅ | ✅ | ❌ |
ㅤ | assign | ✅ | ❌ | ❌ | ❌ |
迭代器支持 | begin() / end() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ❌ 不支持 |
ㅤ | cbegin() / cend() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ❌ 不支持 |
ㅤ | rbegin() / rend() | ✅ 支持 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
ㅤ | crbegin() / crend() | ✅ 支持 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
容量管理 | size() / max_size() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
ㅤ | empty() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
ㅤ | capacity() | ✅ ( vector , deque ) | ❌ | ❌ | ❌ |
ㅤ | reserve() | ✅ ( vector ) | ❌ | ✅ 支持 | ❌ |
ㅤ | resize() | ✅ 支持 | ❌ | ❌ | ❌ |
元素访问 | at() | ✅ ( vector , deque ) | ❌ | ❌ | ❌ |
ㅤ | operator[] | ✅ ( vector , deque ) | ✅ ( map ) | ✅ ( unordered_map ) | ❌ |
ㅤ | front() / back() | ✅ 支持 | ❌ | ❌ | ✅( stack ,queue 的变体) |
修改器 | insert() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ❌ |
ㅤ | emplace() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅(部分支持) |
ㅤ | erase() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ❌ |
ㅤ | push_back() / pop_back() | ✅ ( vector , deque ) | ❌ | ❌ | ❌ |
ㅤ | push_front() / pop_front() | ✅ ( deque , list ) | ❌ | ❌ | ✅( queue 支持) |
ㅤ | clear() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ❌ |
ㅤ | swap() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ✅ |
排序操作 | sort() | ✅ ( list ) | ❌ | ❌ | ❌ |
ㅤ | merge() | ✅ ( list ) | ✅ 支持 | ❌ | ❌ |
ㅤ | unique() | ✅ ( list ) | ❌ | ❌ | ❌ |
ㅤ | reverse() | ✅ ( list ) | ❌ | ❌ | ❌ |
链表特性 | splice() / splice_after() | ✅ ( list , forward_list ) | ❌ | ❌ | ❌ |
查找操作 | find() | ❌ | ✅ 支持 | ✅ 支持 | ❌ |
ㅤ | count() | ✅ ( list ) | ✅ 支持 | ✅ 支持 | ❌ |
ㅤ | lower_bound() / upper_bound() | ❌ | ✅ 支持 | ❌ | ❌ |
ㅤ | equal_range() | ❌ | ✅ 支持 | ✅ 支持 | ❌ |
ㅤ | contains() | ❌ | ✅(C++20 起) | ✅(C++20 起) | ❌ |
观察器 | key_comp() / value_comp() | ❌ | ✅ 支持 | ❌ | ❌ |
哈希操作 | bucket_count() / bucket() | ❌ | ❌ | ✅ 支持 | ❌ |
ㅤ | load_factor() / max_load_factor() | ❌ | ❌ | ✅ 支持 | ❌ |
适配器特性 | top() / front() / back() | ❌ | ❌ | ❌ | ✅( stack ,queue 支持) |
ㅤ | push() / pop() | ❌ | ❌ | ❌ | ✅ 支持 |
分配器 | get_allocator() | ✅ 支持 | ✅ 支持 | ✅ 支持 | ❌ |
进一步说明
- 顺序容器 提供丰富的修改器和迭代器功能,适合动态大小和顺序存储的需求,操作简单但遍历复杂度取决于实现。
- 关联容器 适合存储有序键值对,支持高效查找,但随机访问性能较差。
- 无序关联容器 是关联容器的哈希版本,适合需要快速插入和查找的场景,但对顺序没有要求。
- 容器适配器 提供特定功能(如栈、队列),其功能受到严格限制以适应目标用途。
十八、std::bitset
详解
std::bitset
是 C++ 标准库中的一个容器类,用于管理和操作固定大小的位集合。它提供了一种高效的方式来存储和操作位数据。头文件
特点
- 固定大小:位集合大小在编译时确定,不能动态调整。
- 高效存储:每个位占用 1 位内存,适合处理布尔数据。
- 功能丰富:支持按位操作、位翻转、位访问等操作。
- 适合位操作应用:如位掩码、布尔向量、状态集合等。
构造与初始化
常用成员函数
函数 | 描述 | 示例 |
size() | 返回位集合的大小。 | b1.size(); |
count() | 返回位集合中值为 1 的位数。 | b1.count(); |
any() | 检查是否至少有一个位为 1。 | b1.any(); |
none() | 检查是否所有位都为 0。 | b1.none(); |
all() | 检查是否所有位都为 1。 | b1.all(); |
set() | 将所有位设置为 1,或设置指定位置为 1。 | b1.set(); b1.set(2); |
reset() | 将所有位设置为 0,或设置指定位置为 0。 | b1.reset(); b1.reset(2); |
flip() | 翻转所有位或指定位置的位。 | b1.flip(); b1.flip(2); |
test() | 检查指定位置的位是否为 1。 | b1.test(2); |
operator[] | 返回指定位置位的值(只读访问)。 | b1[2]; |
to_string() | 返回 bitset 的字符串表示。 | b1.to_string(); |
to_ulong() | 将 bitset 转换为无符号长整数(位数不超过 unsigned long 大小)。 | b1.to_ulong(); |
按位操作支持
std::bitset
支持按位操作符(&
, |
, ^
, ~
)和移位操作符(<<
, >>
)。示例:
示例代码
十九、std::pair
详解
std::pair
是 C++ 标准库中的一个简单容器,用于存储两个值(称为 first 和 second)。这两个值可以是不同类型。头文件
特点
- 用于将两个关联值打包成一个单元。
- 常用于返回多个值的函数。
- 提供成员函数和运算符重载。
构造与初始化
常用成员
成员变量 | 描述 | 示例 |
first | 存储第一个值。 | p1.first = 10; |
second | 存储第二个值。 | p1.second = "example"; |
常用函数
函数 | 描述 | 示例 |
make_pair | 创建一个 pair ,推导元素类型。 | auto p = std::make_pair(1, "text"); |
operator== | 检查两个 pair 是否相等。 | if (p1 == p2) {...} |
operator< | 按字典序比较两个 pair ,先比较 first ,若相等则比较 second 。 | if (p1 < p2) {...} |
示例代码
二十、STL中常用算法
STL 中常用算法库详解
C++ 标准模板库(STL)中提供了丰富的算法库,用于操作容器中的元素。算法库主要定义在头文件
<algorithm>
和 <numeric>
中,包括排序、查找、修改、数值计算等多种算法。以下是 STL 算法库中常用算法的分类及其详细说明:
1. 排序算法
算法 | 描述 | 复杂度 | 示例 |
sort | 对范围内元素进行升序排序,支持自定义比较函数。 | std::sort(v.begin(), v.end()); | |
stable_sort | 稳定排序,保证相等元素的相对顺序。 | std::stable_sort(v.begin(), v.end()); | |
partial_sort | 对范围内前 k 个元素排序,其他元素顺序不定。 | std::partial_sort(v.begin(), v.begin() + k, v.end()); | |
nth_element | 将第 n 小的元素放到正确位置,左侧小于 n,右侧大于 n。 | std::nth_element(v.begin(), v.begin() + n, v.end()); | |
is_sorted | 检查范围内的元素是否已经按升序排列。 | bool sorted = std::is_sorted(v.begin(), v.end()); |
2. 查找算法
算法 | 描述 | 复杂度 | 示例 |
find | 查找范围内第一个等于指定值的元素,返回迭代器。 | auto it = std::find(v.begin(), v.end(), value); | |
find_if | 查找满足条件的第一个元素,返回迭代器。 | auto it = std::find_if(v.begin(), v.end(), predicate); | |
find_if_not | 查找第一个不满足条件的元素,返回迭代器。 | auto it = std::find_if_not(v.begin(), v.end(), predicate); | |
binary_search | 在有序范围内进行二分查找,返回是否找到指定值。 | bool found = std::binary_search(v.begin(), v.end(), value); | |
lower_bound | 返回第一个大于等于值的元素迭代器(在有序范围内)。 | auto it = std::lower_bound(v.begin(), v.end(), value); | |
upper_bound | 返回第一个大于值的元素迭代器(在有序范围内)。 | auto it = std::upper_bound(v.begin(), v.end(), value); | |
equal_range | 返回等于值的范围(两个迭代器)。 | auto range = std::equal_range(v.begin(), v.end(), value); |
3. 修改算法
算法 | 描述 | 复杂度 | 示例 |
copy | 将范围内的元素复制到另一个范围。 | std::copy(v.begin(), v.end(), dest.begin()); | |
copy_if | 将满足条件的元素复制到另一个范围。 | std::copy_if(v.begin(), v.end(), dest.begin(), predicate); | |
move | 将范围内的元素移动到另一个范围。 | std::move(v.begin(), v.end(), dest.begin()); | |
transform | 将范围内的元素通过函数变换后复制到另一个范围。 | std::transform(v.begin(), v.end(), dest.begin(), func); | |
replace | 将范围内等于某值的元素替换为另一个值。 | std::replace(v.begin(), v.end(), old_value, new_value); | |
replace_if | 替换满足条件的元素为指定值。 | std::replace_if(v.begin(), v.end(), predicate, new_value); | |
remove | 移动等于指定值的元素到范围末尾,不改变容器大小。 | auto it = std::remove(v.begin(), v.end(), value); | |
remove_if | 移动满足条件的元素到范围末尾,不改变容器大小。 | auto it = std::remove_if(v.begin(), v.end(), predicate); | |
unique | 移动相邻的重复元素到范围末尾,不改变容器大小。 | auto it = std::unique(v.begin(), v.end()); | |
reverse | 反转范围内的元素顺序。 | std::reverse(v.begin(), v.end()); | |
rotate | 将范围内的元素旋转。 | std::rotate(v.begin(), v.middle(), v.end()); |
4. 数值计算算法
算法 | 描述 | 复杂度 | 示例 |
accumulate | 计算范围内元素的累加和,可使用自定义操作。 | int sum = std::accumulate(v.begin(), v.end(), 0); | |
inner_product | 计算两个范围内元素的内积。 | int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0); | |
adjacent_difference | 计算相邻元素的差值并存储到另一范围。 | std::adjacent_difference(v.begin(), v.end(), result.begin()); | |
partial_sum | 计算范围内的部分和(前缀和)。 | std::partial_sum(v.begin(), v.end(), result.begin()); | |
iota | 填充范围内的元素为连续递增值。 | std::iota(v.begin(), v.end(), 0); |
5. 集合操作算法
算法 | 描述 | 复杂度 | 示例 |
set_union | 计算两个范围的并集,结果存储到另一个范围。 | std::set_union(a.begin(), a.end(), b.begin(), b.end(), result.begin()); | |
set_intersection | 计算两个范围的交集,结果存储到另一个范围。 | std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), result.begin()); | |
set_difference | 计算两个范围的差集,结果存储到另一个范围。 | std::set_difference(a.begin(), a.end(), b.begin(), b.end(), result.begin()); | |
set_symmetric_difference | 计算两个范围的对称差集,结果存储到另一个范围。 | std::set_symmetric_difference(a.begin(), a.end(), b.begin(), b.end(), result.begin()); |
6. 其他通用算法
算法 | 描述 | 复杂度 | 示例 |
for_each | 对范围内的每个元素应用指定的操作。 | std::for_each(v.begin(), v.end(), [](int x){ std::cout << x; }); | |
min_element | 返回范围内最小元素的迭代器。 | auto it = std::min_element(v.begin(), v.end()); | |
max_element | 返回范围内最大元素的迭代器。 | auto it = std::max_element(v.begin(), v.end()); | |
minmax_element | 同时返回范围内最小和最大元素的迭代器( std::pair )。 | auto result = std::minmax_element(v.begin(), v.end()); | |
all_of | 检查范围内是否所有元素都满足条件。 | bool result = std::all_of(v.begin(), v.end(), [](int x){ return x > 0; }); | |
any_of | 检查范围内是否至少有一个元素满足条件。 | bool result = std::any_of(v.begin(), v.end(), [](int x){ return x > 0; }); | |
none_of | 检查范围内是否所有元素都不满足条件。 | bool result = std::none_of(v.begin(), v.end(), [](int x){ return x > 0; }); | |
equal | 检查两个范围内的元素是否相等(按顺序比较)。 | bool result = std::equal(v1.begin(), v1.end(), v2.begin()); | |
mismatch | 返回两个范围内首个不匹配的元素对的迭代器。 | auto result = std::mismatch(v1.begin(), v1.end(), v2.begin()); | |
lexicographical_compare | 按字典序比较两个范围,返回是否第一个范围小于第二个范围。 | bool result = std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end()); | |
swap_ranges | 交换两个范围的元素内容。 | std::swap_ranges(v1.begin(), v1.end(), v2.begin()); | |
shuffle | 将范围内的元素按随机顺序重新排列(需要随机数生成器)。 | std::shuffle(v.begin(), v.end(), std::default_random_engine()); |
- 作者:小H狂炫香菜
- 链接:https://hjwvip.top/technology/cpp-STL
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。