哈希表查找
定义与基本思想
哈希表查找(Hash Table Search)是一种通过哈希函数将关键字映射到表中某个位置进行查找的方法。其核心思想是“以空间换时间”,查找效率极高。
哈希表查找演示
此处可扩展为哈希函数、冲突处理等动画。
- 哈希函数映射
- 冲突处理(开放定址/链地址)
- 查找过程演示
适用场景
- 适用于查找频繁、数据量较大的场合
- 适用于对查找效率要求极高的应用
算法描述
- 设计合适的哈希函数 ,将关键字 映射到哈希表的某个位置
- 若该位置为空,则查找失败
- 若该位置存有元素,比较关键字是否相等
- 若冲突,采用冲突处理方法(如开放定址法、链地址法)
伪代码如下:
pos = H(x)
if table[pos] == null:
return -1
elif table[pos].key == x:
return pos
else:
// 冲突处理(如线性探测、链表查找等)
...
哈希函数的构造方法
- 除留余数法:,p 取不大于表长 m 的最大素数,分布最均匀,最常用
- 直接定址法:,适合关键字分布连续
- 数字分析法:取关键字中分布较均匀的若干位
- 平方取中法:取关键字平方的中间几位
- 折叠法:将关键字分割成若干段再相加
冲突处理方法
开放定址法
发生冲突时,在哈希表内寻找下一个空位。
- 线性探测:,容易产生”堆积”
- 平方探测:,可避免堆积
链地址法
把哈希到同一位置的所有元素挂在同一条链表上。查找时先定位链表,再在链表中顺序查找。
#define M 13 // 哈希表长(取素数)
typedef struct Node {
int key;
struct Node *next;
} Node;
// 哈希函数:除留余数法
int H(int key) {
return key % M;
}
// 链地址法查找
Node *HashSearch(Node *hashtable[], int key) {
int pos = H(key);
Node *p = hashtable[pos];
while (p != NULL && p->key != key)
p = p->next; // 在链表中顺序查找
return p; // 返回找到的结点或 NULL
}
// 链地址法插入
void HashInsert(Node *hashtable[], int key) {
int pos = H(key);
Node *s = (Node *)malloc(sizeof(Node));
s->key = key;
s->next = hashtable[pos]; // 头插法
hashtable[pos] = s;
}
装填因子与性能分析
装填因子 ,它直接影响查找性能。
- 越大,冲突越多,查找效率越低
- 链地址法的平均查找长度:
- 线性探测的平均查找长度:
- 工程实践中通常控制 在 0.7~0.8 以下
时间复杂度分析
- 理想情况下:
- 最坏情况下(大量冲突):
- 实际应用中,查找效率接近
习题
习题 1
哈希表查找的基本思想是什么?常见的冲突处理方法有哪些?
答案与解析
解题思路:考查哈希表查找原理和冲突处理。
详细步骤:
- 通过哈希函数将关键字映射到表中位置
- 冲突处理方法有开放定址法、链地址法等
答案:哈希函数映射,冲突处理有开放定址、链地址法等。
习题 2
哈希表查找的平均时间复杂度是多少?在什么情况下会退化为 ?
答案与解析
解题思路:考查复杂度和极端情况。
详细步骤:
- 平均复杂度
- 当哈希函数设计不佳或装填因子过大,冲突严重时,最坏复杂度
答案:平均 ,大量冲突时退化为 。
习题 3
哈希表查找的查找过程包括哪两步?常见的冲突处理方法有哪些?
答案与解析
解题思路:查找流程和冲突处理。
详细步骤:
- 通过哈希函数定位
- 冲突时采用开放定址或链地址法
答案:定位+冲突处理,方法有开放定址、链地址法等。
