散列查找
一、散列函数的构造
原数据的关键字key 通过散列函数 H(key) 映射到新的地址
用一个质数求余 发生冲突的可能性更小
二、散列冲突的解决方案
1.开放地址法
这里的开放地址其实就是一个空位置
开放地址法就是如果发生冲突,就按照规则,寻找空位置;最先找到的空位置就是这个关键字的对应的存储位置
1 | h[i]=(H(key)+d[i])% table_size (i=1,2,...,table_size-1) |
d[i] 一般有三种写法:
- 线性探测 d[i] =1,2,3,…,table_size (其实是d[i] = c* i ,但是c通常取1)
- 二次探测(平方探测再散列):d[i]=1²,-1²,2²,-2²,…,k²,-k² (k<=table_size/2)
- 伪随机探测
(1)线性探测法
冲突后依次探测下一个位置,知道遇到空位置
构建散列表
查找成功和失败的AVL分别如何计算
*注意在教材中,和空位置的比较是不计入比较次数的
( 但是有的地方认为空位置其实是NULL类型,也是一次比较

删除元素时,不能直接把该位置换成空位置的标记(会造成后面的数被误认为不存在),应该设一个删除标记。
增加新的元素时,删除标记和空标记都可以插入新元素,而查找时遇到空位置就代表结束,遇到删除标记则继续查找
(2)平方探测
d[i]=1²,-1²,2²,-2²,…,k²,-k² (k<=table_size/2)
缺点是不一定能探测到所有散列表位置
但是研究表明,表长如果是某个4k+3的质数(7,11…),那么一定能探测到所有的位置
删除也是设删除标记


(3)随机

2.再散列法
1 | h[i]=RH(key); (i=1,2,3...,n) |
就是有n个不同的散列函数,当第一个有冲突时,就用第二个散列函数计算的结果,以此类推
3.链地址法
把所有映射到同一个位置的关键字用一个链表串起来

ASL(成功)= ∑(每一层元素的个数 * 这一层相应的比较次数)/元素个数
ASL(失败)= ∑每个链表找到空位置时需要的比较个数(每个槽中的元素个数) / 链表的个数(槽的个数)
删除的话就直接删。
相关代码
这是deepseek帮我翻译的代码,我还没仔细读,先放在这存着
以下是伪代码转换后的C++代码,包含详细注释:
1 |
|
代码说明:
数据结构:
HashEntry结构体表示散列表中的每个项,包含键、值和状态。HashTable类封装了开放地址法的核心逻辑,使用vector存储表项。
关键函数:
searchHash:根据键查找位置,处理冲突直到找到目标键或空位。insertHash:调用searchHash找到合适位置,仅在状态非ACTIVE时插入新元素。
冲突解决:
solveCollision示例为线性探测(步长+1),可根据需求改为二次探测(如返回count * count)。
扩展性:
- 可修改
hashFunction和solveCollision实现不同的散列函数和冲突策略。 - 插入时若表满,可添加扩容逻辑(如重新散列到更大的表)。
- 可修改
使用示例:
1 | int main() { |
- 标题: 散列查找
- 作者: Wiliyaya
- 创建于 : 2025-05-18 15:01:12
- 更新于 : 2025-05-26 20:12:22
- 链接: https://redefine.ohevan.com/2025/05/18/散列查找/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论