一、HashTable(哈希表)
(1)HashTable与其核心思想
哈希表(Hash Table)是一种基于哈希函数的键值映射数据结构,它能在O(1) 的均摊时间复杂度内完成查找、插入和删除操作。
核心思想:
- 通过哈希函数(Hash Function) 计算键的哈希值,映射到一个索引位置。
- 若索引位置冲突(两个键映射到相同索引),使用冲突解决策略(如链地址法或开放寻址法) 处理。
- 负载因子(Load Factor) 影响哈希表性能,通常超过阈值时会进行动态扩容。
其中,负载因子是指哈希表中已存储元素数量与总容量的比值,用于衡量哈希表的填充程度。
(2)HashTable的实现
STL 容器 | 底层实现 | 是否有序 | 允许重复键/值 |
---|---|---|---|
unordered_map | 哈希表 | ❌ | ❌ |
unordered_multimap | 哈希表 | ❌ | ✅ |
unordered_set | 哈希表 | ❌ | ❌ |
unordered_multiset | 哈希表 | ❌ | ✅ |
使用建议:
- 需要 O(1) 查找?用
unordered_map
(哈希表)。 - 需要唯一键值?用
unordered_set
(哈希集合)。 - 需要允许重复键?用
unordered_multimap
。 - 需要允许重复值?用
unordered_multiset
。
(3)红黑树(map
) vs 哈希表(unordered_map
)
红黑树 (map ) | 哈希表 (unordered_map ) | |
---|---|---|
底层结构 | 红黑树 | 哈希表 |
插入/删除/查找 | O(log n) | O(1)(均摊) |
是否有序 | 是(按键排序) | 否(无序存储) |
适用场景 | 需要排序、范围查询 | 仅关心查找速度 |
二、unordered_map
(哈希表的键值映射)
(1)常用函数
函数 | 作用 |
---|---|
insert({Key, Value}) | 插入键值对 |
find(Key) | 查找键,返回迭代器(不存在则 end() ) |
erase(Key) | 删除键 |
count(Key) | 返回键的个数(对于 unordered_map 只能是 0 或 1 ) |
size() | 返回元素个数 |
clear() | 清空哈希表 |
(2)基本使用
#include <iostream>
using namespace std;
#include <unordered_map>
#include <string>
int main() {
unordered_map<string, int> hash_table;
// 插入键值对
hash_table["Apple"] = 10;
hash_table["Banana"] = 20;
hash_table["Cherry"] = 30;
// 查找键值对
if (hash_table.find("Banana") != hash_table.end())
{
cout << "Banana 的值是: " << hash_table["Banana"] << endl;
}
// 遍历哈希表(无序)
cout << "哈希表内容:" << endl;
for (const auto& pair : hash_table)
{
cout << pair.first << " -> " << pair.second << endl;
}
system("pause");
return 0;
}
注意:
unordered_map
中采用无序存储。- 查找
find()
的复杂度为O(1) 。 []
访问键时,若键不存在,会创建默认值。
三、unordered_set
(哈希表的无序集合)
(1)常用函数
函数 | 作用 |
---|---|
insert(Value) | 插入元素 |
find(Value) | 查找元素,返回迭代器 |
erase(Value) | 删除元素 |
count(Value) | 返回元素个数(只能是 0 或 1 ) |
size() | 返回集合大小 |
clear() | 清空集合 |
(2)基本使用
#include <iostream>
using namespace std;
#include <unordered_set>
int main() {
unordered_set<int> hash_set = {10, 20, 30, 40};
// 插入元素
hash_set.insert(50);
hash_set.insert(30); // 30 已存在,不会重复插入
// 查找元素
if (hash_set.find(20) != hash_set.end())
{
cout << "20 存在于哈希集合中" << endl;
}
// 遍历哈希集合(无序)
cout << "哈希集合中的元素: ";
for (int num : hash_set)
{
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
unordered_set
基于哈希表实现集合(元素唯一,自动去重)。- 采用无序存储,适用于快速去重、判重、查找。
- 查找
find()
的复杂度为O(1) 。
四、unordered_multimap
和 unordered_multiset
(允许重复键/值的哈希表)
unordered_multimap
——允许 重复键 的无序哈希表。unordered_multiset
——允许 重复值 的无序哈希集合。
(1)unordered_multimap
的使用
#include <iostream>
using namespace std;
#include <unordered_map>
#include <string>
int main() {
unordered_multimap<int, string> multi_hash_map;
// 插入重复键
multi_hash_map.insert({ 1, "Apple" });
multi_hash_map.insert({ 2, "Banana" });
multi_hash_map.insert({ 1, "Avocado" }); // 允许重复键
// 遍历哈希表
cout << "unordered_multimap 内容:" << endl;
for (const auto& pair : multi_hash_map)
{
cout << pair.first << " -> " << pair.second << endl;
}
system("pause");
return 0;
}
注意:
unordered_multimap
允许多个相同键,适用于数据库索引等。
(2)unordered_multiset
的使用
#include <iostream>
using namespace std;
#include <unordered_set>
int main() {
unordered_multiset<int> hash_multiset = { 10, 20, 30 };
// 插入元素
hash_multiset.insert(20); // 允许重复值
hash_multiset.insert(30); // 允许重复值
hash_multiset.insert(40);
// 遍历哈希集合(无序)
cout << "哈希集合中的元素: ";
for (int num : hash_multiset)
{
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}