std::unordered_set 和 std::unordered_map 的 核心设计思想相似(均基于哈希表实现,提供 O(1) 平均时间复杂度的查找),但它们的 API 并不完全相同,主要区别源于二者用途不同:
• unordered_map 存储键值对(key-value),需通过键访问值。
• unordered_set 仅存储键(key),用于快速判断元素是否存在。
1. 相同点
以下 API 在两者中功能一致:
| 操作 | 功能说明 | 示例(unordered_map / unordered_set) |
|---|---|---|
insert() | 插入元素 | map.insert({key, value}) / set.insert(key) |
emplace() | 直接构造元素(避免拷贝) | map.emplace(key, value) / set.emplace(key) |
erase() | 删除指定元素 | map.erase(key) / set.erase(key) |
find() | 查找元素,返回迭代器 | auto it = map.find(key) / auto it = set.find(key) |
count() | 返回元素是否存在(0 或 1) | if (map.count(key)) / if (set.count(key)) |
size() | 返回元素数量 | map.size() / set.size() |
empty() | 判断容器是否为空 | map.empty() / set.empty() |
clear() | 清空所有元素 | map.clear() / set.clear() |
begin(), end() | 返回迭代器 | 用于遍历容器 |
2. 不同点
(1)元素访问
• unordered_map 提供 operator[] 和 at() 直接访问值:
unordered_map<string, int> map = {{"Alice", 25}};
cout << map["Alice"]; // 输出 25(若 key 不存在会自动插入默认值!)
cout << map.at("Alice"); // 输出 25(若 key 不存在抛出异常)
unordered_set 没有这些接口,因为它不存储值。
(2)迭代器解引用
• unordered_map 的迭代器指向 pair<const Key, T>,需用 it->first 和 it->second 访问键和值:
for (auto it = map.begin(); it != map.end(); ++it) {
cout << it->first << ": " << it->second; // 输出键值对
}
• unordered_set 的迭代器直接指向 Key:
unordered_set<int> set = {1, 2, 3};
for (auto it = set.begin(); it != set.end(); ++it) {
cout << *it; // 输出元素值
}
(3)初始化与插入
• unordered_map 插入键值对需用 {key, value}:
map.insert({"Bob", 30});
• unordered_set 只需插入键:
set.insert(42);
3. 何时选择?
• 用 unordered_map:
需要建立 键到值的映射(如统计词频、缓存键值对)。
unordered_map<string, int> word_count;
word_count["hello"]++; // 统计单词出现次数
• 用 unordered_set:
只需 快速判断元素是否存在(如去重、检查重复)。
unordered_set<int> seen;
if (seen.count(num)) return true; // 检查重复数字
4. 性能注意事项
• 两者均为哈希实现,但 unordered_map 存储更多数据(需存值),内存占用略高。
• 均需注意哈希冲突,复杂键类型需自定义哈希函数(如对自定义类或 pair 哈希)。
总结
• 相同点:插入、删除、查找等基础操作接口一致。
• 不同点:
• unordered_map 提供键值对访问([]、at),迭代器解引用为 pair。
• unordered_set 仅存储键,更轻量级。
根据场景选择:需要关联值时用 map,只需存在性检查时用 set。
1万+

被折叠的 条评论
为什么被折叠?



