C++ STL(标准模板库)学习
C++ STL(标准模板库)
- map映射
- map:有序键值对容器
- unordered_map:无序键值对容器
- map和unordered_map的遍历
- set集合
- set:有序集合
- unordered_set:无序集合
- set 和 unordered_set 的遍历
map映射
存储键值对集合(存储 key和对应的 value)
map:有序键值对容器
1. 内部实现
基于红黑树(Red-Black Tree) 实现,这是一种自平衡的二叉搜索树。红黑树通过颜色规则和旋转操作维持平衡,确保树的高度为 O(log n),从而保证操作效率的稳定性。
2. 核心特性
- 有序性:键(key)会按照默认的升序规则(可通过自定义比较器修改)自动排序,遍历 map 时会按 key 的顺序输出。
- 键唯一性:key 不允许重复,插入重复 key 会覆盖原有 value。
- 操作效率:插入、删除、查找操作的时间复杂度均为 O(log n)(不受数据分布影响,稳定性高)。
- 支持范围查询:可通过 lower_bound、upper_bound 等接口快速查找某个 key 的上下界,适合区间操作(如查找 key 在 [a, b] 范围内的键值对)。
3. 常用接口示例
#include <map>
using namespace std;map<int, string> mp;
// 插入键值对(自动按key排序)
mp.insert({1, "a"});
mp[2] = "b"; // 另一种插入方式// 查找
auto it = mp.find(1); // 返回迭代器,指向key=1的键值对
if (it != mp.end()) {string val = it->second; // 获取value
}// 范围查询:查找key >= 1的第一个元素
auto lb = mp.lower_bound(1);
4. 适用场景
需要键有序存储、频繁进行范围查询(如找最小值、最大值或某个区间的键值对),或对操作效率的稳定性要求较高(不接受最坏情况的性能波动)。
unordered_map:无序键值对容器
1. 内部实现
基于哈希表(Hash Table) 实现,通过哈希函数将 key 映射到哈希表的桶(Bucket)中,实现快速访问。
2. 核心特性
- 无序性:键值对的存储顺序与插入顺序无关,遍历结果是无序的。
- 键唯一性:同样不允许重复 key,插入重复 key 会覆盖原有 value。
- 操作效率:插入、删除、查找的平均时间复杂度为 O(1)(依赖哈希函数的均匀性),但最坏情况下(哈希冲突严重)会退化到 O(n)(实际中通过良好的哈希策略可避免)。
- 不支持范围查询:因元素无序,无法高效进行区间操作(如 lower_bound 无意义)。
3. 常用接口示例
#include <unordered_map>
using namespace std;unordered_map<int, string> ump;
// 插入键值对(无序存储)
ump.insert({1, "a"});
ump[2] = "b";// 查找(平均O(1))
auto it = ump.find(1);
if (it != ump.end()) {string val = it->second;
}
4. 适用场景
不需要键有序,追求快速的查找 / 插入效率(如缓存、字典查询),且数据量较大(哈希表的 O(1) 优势在大数据量下更明显)。
map和unordered_map的遍历
map 中每个元素是 pair<key_type, value_type>
,需通过 ->first
访问 key
,->second
访问 value
(unordered_map 的遍历方式与 map 完全相同,仅内部存储无序,遍历结果无固定顺序。)
#include <iostream>
#include <map>
using namespace std;int main() {map<int, string> mp = {{1, "a"}, {2, "b"}, {3, "c"}};// 方法1:范围for循环(推荐,C++11及以上)for (const auto& pair : mp) { // pair是const引用,避免拷贝cout << "key: " << pair.first << ", value: " << pair.second << endl;}// 方法2:迭代器遍历for (map<int, string>::iterator it = mp.begin(); it != mp.end(); ++it) {cout << "key: " << it->first << ", value: " << it->second << endl;}return 0;
}
set集合
存储单值集合(仅存储 key,不存储 value)
set:有序集合
1. 内部实现
set 基于红黑树(Red-Black Tree) 实现,这是一种自平衡的二叉搜索树(BST)。红黑树通过颜色规则和旋转操作维持平衡,确保树的高度始终为 O(log n)。
2. 核心特性
- 有序性:元素会按照默认升序(可通过自定义比较器修改排序规则)自动排序,遍历 set 时会按顺序输出。
- 唯一性:插入重复元素时会被忽略(不会存储)。
- 操作效率:插入、删除、查找操作的时间复杂度均为 O(log n)(依赖红黑树的平衡特性)。
- 支持高效的范围查询(如 lower_bound、upper_bound 查找某个值的上下界)。
3. 常用接口
set<int> s;
s.insert(3); // 插入元素(自动排序)
s.erase(3); // 删除元素
auto it = s.find(3); // 查找元素,返回迭代器(未找到则为 s.end())
bool exists = s.count(3); // 判断元素是否存在(返回 0 或 1)
s.lower_bound(2); // 返回第一个 >= 2 的元素迭代器
s.upper_bound(5); // 返回第一个 > 5 的元素迭代器
4. 适用场景
- 需要元素有序存储或频繁进行范围查询(如找某个区间内的元素)。
- 对插入 / 删除 / 查找的效率要求为 O (log n),且不追求极致的常数时间优化。
unordered_set:无序集合
1. 内部实现
unordered_set 基于哈希表(Hash Table) 实现,通过哈希函数将元素映射到桶(Bucket)中,实现快速访问。
2. 核心特性
- 无序性:元素存储顺序与插入顺序无关,遍历结果是无序的。
- 唯一性:同样不允许重复元素,插入重复值会被忽略。
- 操作效率:插入、删除、查找操作的平均时间复杂度为 O (1)(依赖哈希函数的均匀性)。
- 最坏情况下(哈希冲突严重,所有元素映射到同一桶)时间复杂度会退化到 O (n),但实际中通过良好的哈希函数可避免。
3. 常用接口
unordered_set<int> us;
us.insert(3); // 插入元素(无序存储)
us.erase(3); // 删除元素
auto it = us.find(3); // 查找元素,返回迭代器(未找到则为 us.end())
bool exists = us.count(3); // 判断元素是否存在(返回 0 或 1)
// C++20 新增:us.contains(3) 更直观地判断存在性
4. 适用场景
- 不需要元素有序,追求插入、删除、查找的高效性(接近 O (1))。
- 数据量较大,且对时间复杂度敏感( Leetcode 128. 最长连续序列 问题要求 O (n) 时间)。
set 和 unordered_set 的遍历
set 中每个元素就是 key,直接访问元素即可(无需区分 key 和 value),unordered_set遍历方式与 set 相同,但元素无序,遍历结果无固定顺序。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> s = {1, 2, 3};// 方法1:范围for循环for (int num : s) { // 元素有序,按升序输出cout << num << endl;}// 方法2:迭代器遍历for (set<int>::iterator it = s.begin(); it != s.end(); ++it) {cout << *it << endl; // 通过*it访问元素}return 0;
}