1. 简介
哈希表(Hash Table),也称为散列表,是一种通过哈希函数将键(Key)映射到表中一个位置以便快速访问记录的数据结构。它提供了快速的数据插入、删除、搜索和访问功能。哈希表的主要目的是解决直接寻址和顺序结构之间的矛盾,实现快速的数据访问。
1.1 哈希表的基本组成
-
哈希函数(Hash Function):将键通过某种算法转换为数组索引的函数。一个好的哈希函数应该能够均匀地将键分布在哈希表中,以减少冲突。(hash = key % table_size)
-
哈希表数组:一个线性数组,用于存储键值对。数组的每个位置称为一个槽(Slot)或桶(Bucket)。
-
键值对(Key-Value Pairs):哈希表中存储的数据元素,每个元素包含一个键和一个与之关联的值。
1.2 哈希表的操作
-
插入(Insert):
-
计算键的哈希值。
-
将键值对存储在哈希表数组的对应位置。
-
如果发生冲突(即两个键映射到同一个位置),需要解决冲突,常见的方法有链地址法(Chaining)和开放寻址法(Open Addressing)。
-
-
搜索(Search):
-
计算键的哈希值。
-
在哈希表数组的对应位置查找键。
-
如果键存在,返回对应的值;如果不存在,返回未找到。
-
-
删除(Delete):
-
计算键的哈希值。
-
在哈希表数组的对应位置找到键。
-
删除键值对。
-
1.3 冲突策略
-
拉链法
-
在每个哈希表槽位上维护一个链表。
-
当发生冲突时,将冲突的元素添加到对应槽位的链表中。
-
搜索时,需要遍历链表以找到特定的键。
-
优点是实现简单,缺点是链表过长时性能下降。
-
-
开放寻址法
-
所有元素直接存储在哈希表中,不使用链表。
-
当发生冲突时,使用探测序列在哈希表中寻找下一个空闲槽位。
-
常见的探测方法包括线性探测、二次探测和双重哈希。
-
优点是空间利用率高,缺点是删除操作复杂,可能导致聚集。
-
注:
-
双重哈希
-
是开放寻址法的一种,使用两个哈希函数。
-
第一个哈希函数确定初始槽位,第二个哈希函数确定探测步长。
-
优点是减少了聚集,性能更稳定。
-
-
线性探测
-
在发生冲突时,线性地探测下一个空闲位置。
-
例如,如果
hash(key)
产生冲突,尝试hash(key) + 1
,hash(key) + 2
,依此类推。 -
优点是实现简单,缺点是容易产生聚集。
-
-
二次探测
-
类似于线性探测,但是探测步长是二次方增长的。
-
例如,
hash(key) + 1^2
,hash(key) + 2^2
,hash(key) + 3^2
,等等。 -
优点是减少了聚集,比线性探测更均匀。
-
2. 示例
数据:23,2,4,5,68,7,34
hash表长度:7
hash映射函数:hash = key % table_size
原始哈希表:
2.1 拉链法
hash取余:
23 % 7 = 2;2 %7 = 2;4 % 7 = 4; 5 % 7 = 5; 68 % 7 = 5;7 % 7 = 0; 34 % 7 = 6;
映射图:
2.2 开放寻址法
采用线性探测方法映射