哈希表(Hash Table)是一种高效的数据结构,用于通过键(Key)快速存储和检索值(Value)。它通过哈希函数 将键映射到数组的特定索引位置,从而实现平均时间复杂度为 O(1) 的插入、删除和查找操作。以下是其核心概念和实现细节的总结:
1. 核心组成
- 哈希函数 :将键转换为数组索引的函数。理想情况下,函数应均匀分布键值,减少冲突。
- 示例:
hash(key) = key % array_size(简单取模,但可能不均匀)。
- 示例:
- 数组(桶/Bucket):存储键值对的容器,索引由哈希函数决定。
- 冲突解决 :当不同键映射到同一索引时,需处理冲突:
- 链地址法(Separate Chaining):每个索引位置维护一个链表,存储冲突的键值对。
- 开放寻址法(Open Addressing):冲突时按规则(如线性探测、二次探测)寻找下一个空槽。
2. 操作流程
- 插入(Insert) :
- 计算键的哈希值,确定数组索引。
- 若位置为空,直接插入;若冲突,按策略处理(如添加到链表或寻找新位置)。
- 查找(Search) :
- 计算键的哈希值,定位索引。
- 若位置无冲突,直接返回;否则遍历冲突结构(如链表)查找键。
- 删除(Delete) :
1 类似查找,找到后移除键值对(需处理标记删除等开放寻址的细节)。
3. 关键特性
- 时间复杂度 :
- 理想情况(无冲突):O(1)。
- 最坏情况(所有键冲突):O(n)(链表退化为链表,或开放寻址需遍历整个表)。
- 负载因子(Load Factor) :
- 定义:
α = 元素数量 / 数组大小。 - 当α超过阈值(如0.75),需扩容(Rehashing):重新分配更大数组,重新计算所有键的哈希值。
- 定义:
4. 哈希函数设计
- 要求 :
- 确定性:相同键始终映射到同一索引。
- 高效性:计算应快速。
- 均匀性:尽量减少冲突。
- 常见方法 :
- 乘法哈希、除法哈希、全域哈希(如加密哈希函数SHA-256)。
- 字符串键:可结合字符ASCII码和多项式滚动哈希(如Java的
String.hashCode())。
5. 应用场景
- 字典/映射 :如Python的
dict、Java的HashMap。 - 缓存:快速查找缓存数据(如Redis)。
- 数据库索引:加速数据检索。
- 频率统计:统计词频、出现次数等。
6. 代码示例(Python字典模拟)
python
class HashTable:
def __init__(self, size=10):
self.size = size
self.table = [[] for _ in range(size)] # 链地址法
def hash_func(self, key):
return hash(key) % self.size # 简化版哈希函数
def insert(self, key, value):
index = self.hash_func(key)
bucket = self.table[index]
# 检查键是否已存在
for i, (k, v) in enumerate(bucket):
if k == key:
bucket[i] = (key, value) # 更新值
return
bucket.append((key, value)) # 新键插入链表尾部
def search(self, key):
index = self.hash_func(key)
bucket = self.table[index]
for k, v in bucket:
if k == key:
return v
return None # 未找到
def delete(self, key):
index = self.hash_func(key)
bucket = self.table[index]
for i, (k, v) in enumerate(bucket):
if k == key:
del bucket[i]
return
raise KeyError("Key not found")
7. 优化方向
- 动态扩容:根据负载因子自动调整数组大小。
- 更好的哈希函数:减少冲突(如使用更复杂的算法)。
- 开放寻址优化:如双重哈希(Double Hashing)减少聚集。
哈希表是计算机科学中平衡时间与空间效率的经典设计,理解其原理对优化系统性能至关重要。