unordered_map
和 unordered_set
都是 C++ 标准库中的哈希表容器,它们都存储元素并通过哈希函数来优化查找、插入和删除操作。但它们之间有一些重要的区别,下面详细解释:
1. 数据结构类型的不同
unordered_map
:是一个 关联容器,它存储键值对(key-value pair)。每个元素由键(key)和值(value)组成,键是唯一的,可以通过键快速查找对应的值。- 语法:
unordered_map<KeyType, ValueType>
- 语法:
unordered_set
:是一个 集合容器,它只存储键(key),不存储值。集合中的每个元素都是唯一的,且通过哈希值来进行查找。- 语法:
unordered_set<ElementType>
- 语法:
2. 存储元素的方式
unordered_map
:存储的是 键值对。每个元素是一个包含键和值的 pair,键值对的形式是pair<const KeyType, ValueType>
。查找时通过键(key)来获取对应的值(value)。unordered_map<string, int> map; map["apple"] = 5; // 键 "apple",值 5 map["banana"] = 3; // 键 "banana",值 3
unordered_set
:存储的是 单独的键,不包含值。每个元素仅由一个键组成,集合中的元素是唯一的。unordered_set<string> set; set.insert("apple"); // 元素 "apple" set.insert("banana"); // 元素 "banana"
3. 用途不同
unordered_map
:当你需要存储一组关联的键值对,并且想通过键快速查找对应的值时,使用unordered_map
。unordered_set
:当你只关心元素是否存在,而不关心元素的具体值时,使用unordered_set
。例如,你可以用它来存储不重复的元素,并进行集合操作(如求交集、并集等)。
4. 查找与访问
unordered_map
:通过 键 查找 值。可以使用map[key]
访问或修改值,也可以使用find()
来查找键是否存在。unordered_map<string, int> map; map["apple"] = 5; cout << map["apple"]; // 输出 5 // 查找元素 auto it = map.find("banana"); if (it != map.end()) { cout << it->second; // 输出对应的值 }
unordered_set
:通过 键 查找 是否存在。可以使用find()
或count()
来检查某个元素是否在集合中。unordered_set<string> set; set.insert("apple"); // 查找元素 if (set.find("apple") != set.end()) { cout << "Found apple!"; }
5. 常用操作
unordered_map
:insert()
: 插入一个键值对。find()
: 查找键并返回对应的迭代器。operator[]
: 通过键访问或修改对应的值。erase()
: 删除指定键的元素。
unordered_set
:insert()
: 插入一个元素。find()
: 查找元素并返回对应的迭代器。count()
: 检查元素是否存在。erase()
: 删除指定元素。
6. 存储和访问时间复杂度
unordered_map
和unordered_set
都基于哈希表实现,因此它们的 插入、删除、查找 的平均时间复杂度都是 O(1)。不过,在最坏情况下(哈希冲突非常严重时),这些操作的时间复杂度可能退化到 O(n)。
7. 内存使用
unordered_map
:每个元素包含一个键和一个值,因此它的内存开销会比unordered_set
大。unordered_set
:只存储键,因此内存开销比unordered_map
小。
8. 迭代顺序
unordered_map
和unordered_set
都不保证元素的顺序。它们内部使用哈希表存储元素,哈希表并不维护插入顺序或任何特定的顺序。因此,遍历unordered_map
或unordered_set
时,元素的顺序是不可预测的。
9. 使用场景举例
unordered_map
:- 用于存储频率计数:例如,统计每个单词在文本中出现的次数。
- 用于存储配置项:例如,查找配置信息。
unordered_set
:- 用于去重:例如,查找一个数组中的唯一元素。
- 用于集合运算:例如,检查两个集合的交集。
示例代码:
unordered_map
示例:
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<string, int> map;
map["apple"] = 5;
map["banana"] = 3;
map["cherry"] = 7;
// 查找
if (map.find("banana") != map.end()) {
cout << "Found banana, count: " << map["banana"] << endl;
}
// 修改
map["banana"] = 10;
// 遍历
for (const auto& entry : map) {
cout << entry.first << ": " << entry.second << endl;
}
return 0;
}
unordered_set
示例:
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
unordered_set<string> set;
set.insert("apple");
set.insert("banana");
set.insert("cherry");
// 查找
if (set.find("banana") != set.end()) {
cout << "Found banana!" << endl;
}
// 删除
set.erase("banana");
// 遍历
for (const auto& elem : set) {
cout << elem << endl;
}
return 0;
}
总结:
unordered_map
:存储 键值对,通过 键 查找 值,适用于需要通过键访问值的场景。unordered_set
:存储 单个键,适用于需要存储不重复的元素,并检查其是否存在的场景。