🚀 哈希表(Hash Table)详解
哈希表(Hash Table)是一种基于数组和哈希函数的高效数据结构,它可以在平均 O(1) 时间复杂度下完成查找、插入和删除。
📌 1. 哈希表的核心概念
(1)基本原理
- 哈希表使用一个哈希函数(
Hash Function
) 将键(key)映射到一个索引(index)。 - 这个索引指向一个存储值(value)的数组位置,这样查找数据只需要 O(1) 的时间。
(2)核心组成
- 哈希函数 (
Hash Function
):计算 key 在哈希表中的位置。 - 数组 (
Buckets
):用于存储实际数据。 - 冲突处理 (
Collision Resolution
):解决多个 key 计算出的哈希值相同的情况。
📌 2. 哈希表的示例
🌟 C++ unordered_map
使用示例
C++ STL 中的 unordered_map
底层实现就是哈希表。
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<string, int> hashTable;
hashTable["apple"] = 3;
hashTable["banana"] = 5;
hashTable["orange"] = 2;
// 查找 key
if (hashTable.find("banana") != hashTable.end()) {
cout << "banana 的值是 " << hashTable["banana"] << endl;
}
// 遍历哈希表
for (auto &p : hashTable) {
cout << p.first << ": " << p.second << endl;
}
return 0;
}
💡 特点:
unordered_map
使用哈希表存储键值对,查找、插入、删除的平均时间复杂度为O(1)
。- 由于key 通过哈希函数计算存储位置,它的存储顺序是无序的。
- 比
map
更快(map
是红黑树,操作复杂度O(log n)
)。
📌 3. 哈希表的底层实现
(1)哈希函数(Hash Function)
哈希函数的作用是:
- 接收一个 key,计算出一个哈希值(hash value)
- 哈希值再映射到数组的索引,用于快速存储和查找。
举例:假设我们有一个哈希表大小为 10
,一个哈希函数:
hash(key) = key % 10
如果插入以下 key:
Key = 15, Hash(15) = 15 % 10 = 5 → 存入索引 5
Key = 27, Hash(27) = 27 % 10 = 7 → 存入索引 7
Key = 18, Hash(18) = 18 % 10 = 8 → 存入索引 8
📌 这样,查找 key 只需要计算 hash(key)
,直接跳到数组索引位置即可!
(2)哈希冲突(Hash Collision)
当两个 key 计算出的哈希值相同时,就会发生哈希冲突,常见解决方法:
-
链地址法(Separate Chaining)
- 每个数组索引存储一个链表,冲突的 key 追加到链表末尾。
- STL 的
unordered_map
就是基于链地址法实现的。
-
开放地址法(Open Addressing)
- 发生冲突时,寻找下一个空闲位置存储 key。
- 线性探测法(Linear Probing):如果位置冲突,尝试
hash(key) + 1
、hash(key) + 2
…
📌 C++ STL 的 unordered_map
采用“链地址法”来处理冲突!
📌 4. 哈希表 VS 红黑树(Map)
数据结构 | 底层结构 | 查找复杂度 | 插入删除复杂度 | 是否有序 |
---|---|---|---|---|
unordered_map | 哈希表(Hash Table) | O(1) 平均 | O(1) 平均 | ❌ 无序 |
map | 红黑树(Red-Black Tree) | O(log n) | O(log n) | ✅ 有序 |
📌 什么时候用哈希表?
- 当不关心顺序,需要快速查找、插入、删除时,优先使用
unordered_map
。 - 当需要有序存储时,使用
map
。
📌 5. C++ STL 中的哈希表
✅ unordered_set
(无序集合)
底层:哈希表
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
unordered_set<int> us = {1, 5, 8, 3};
us.insert(10);
if (us.find(5) != us.end()) {
cout << "5 存在" << endl;
}
return 0;
}
✅ unordered_map
(无序映射)
底层:哈希表
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<string, int> um;
um["apple"] = 5;
um["banana"] = 3;
cout << um["apple"] << endl; // 5
return 0;
}
📌 6. 总结
🚀 哈希表的优点
✅ 查找、插入、删除速度快(O(1) 平均)
✅ 适合需要频繁查询的数据结构
🚨 哈希表的缺点
❌ 无法保证元素有序
❌ 可能会发生哈希冲突,影响性能(最坏情况 O(n))
🎯 面试常见考点
- 哈希冲突的解决方法(链地址法、开放地址法)
- 什么时候用
unordered_map
,什么时候用map
? - C++ STL
unordered_map
和map
的底层实现(哈希表 vs 红黑树)
📢 总结:
- 哈希表 = 数组 + 哈希函数
- C++ STL 的
unordered_map
、unordered_set
采用哈希表存储 - 平均查找、插入、删除时间复杂度 O(1),比
map
更快!
希望这个详细解析能帮助你彻底理解哈希表!🔥🔥🔥