散列法(hash法、关键字地址计算法)

本文介绍了散列法的基本概念,包括其存储原理、时间复杂度,以及构造哈希函数的多种方法,如除留余数法、数字分析法等。同时讨论了如何处理地址冲突的问题,比如开放定址法和链地址法。最后给出了哈希表的查找、插入、创建及删除等基本操作。
部署运行你感兴趣的模型镜像

散列法,又称为hash法或者关键字地址计算法。时间复杂度为0(理想情况下),是一种key-value的存储方法。核心就是由hash函数决定关键字值和散列地址之间的关系,通过这种关系来组织存储并进行查找等操作。

散列法面临的问题:会发生地址冲突。
(1)如何恰当的构造hash函数,使得结点分布均匀,尽量少的减少冲突。
(2)一旦发生冲突,怎样处理冲突。

以下篇幅主要介绍hash函数的常用构造方法、处理冲突的方法以及和哈希表有关的算法。

这里写图片描述

接下来详细描述这几种构造方法:
① 除留余数法:用每个关键字的value值对p取余,用余数来填hash表。
p取小于或等于表长的最大素数。
② 数字分析法:取每个关键字的某几位作为hash表的地址。
③ 平方取中法:先将每个关键字平方,再按照数字分析法来取中间的几位作为hash表的地址。
④ 分段叠加法:将关键字分成位数相同的几部分,再叠加,用叠加后的结果中的某几位作为hash表的地址。叠加方式分为移位叠加和折叠叠加。
⑤ 基数转换法:将关键字看成另一种进制的数,再转换成为原进制,再取某几位作为散列的地址。

这里写图片描述

接下来详细描述处理冲突的方法:
处理冲突的实际含义就是为产生冲突的地址寻找下一个散列地址。
(1)开放定址法:又被称为再散列法。
① 线性探测再散列:需要注意的是整个表是一个首尾连接的循环表, 每次遇到冲突时位置向后移一位。
② 二次探测再散列:整个表也是一个首尾相接的循环表,每次遇到冲突时位置按照1* 1, 2 * 2,3*3的位置变换顺序左右跳跃式判断。
③ 随机探测再散列:建立一个随机数发生器,并给定一个随机数作为起始点,按随机数的值确定下一个散列地址。

(2)链地址法:把所有具有地址冲突的关键字链在同一个单链表中。

这里写图片描述

接下来介绍哈希表的简单操作算法:
(1)查找过程:
① 根据待查找记录的关键字和建表时的哈希函数计算散列地址。
② 若该地址所对应的地址单元为空,则查找失败,若不为空,则将该单元中的关键字和待查记录的关键字进行比较,如果相等,则查找成功,否则按处理冲突的办法寻找下一个散列地址。

(2)插入过程:
① 通过查找算法找出待插记录在表中的位置,若表中已存在待插记录,则不能再插入。
② 若表中没有待插记录,则需要插入,插入方法是根据查找算法给出一个单元空闲的散列地址,插入即可。

(3) 创建过程:
基于插入算法,依次在一个空表中插入给定序列的关键字。

(4) 删除过程:
基于开放定址法的哈希表没办法真正实现删除操作,只能给被删除结点设置删除标志。
如果执行真正的删除操作,会中断查找路径,删除关键字后找不到比它晚插入且发生过冲突的记录。
如果要对哈希表实现真正的删除操作,最好利用链地址法处理冲突的哈希表。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

### 整型关键字的平方探测散列原理 平方探测是一种处理散列冲突的开放定址。在散列过程中,当发生冲突时,即不同的关键字通过散列函数计算得到了相同的散列地址,就需要寻找其他的空闲位置来存储这些冲突的关键字。 设散列表的长度为 \(m\),散列函数为 \(h(key)\),对于整型关键字 \(key\),其初始散列地址为 \(h_0 = h(key)\)。当发生冲突时,平方探测按照以下公式依次探测新的地址: \(h_i=(h_0 \pm i^2) \bmod m\),其中 \(i = 1, 2, 3, \cdots\) 具体来说,先尝试 \(h_1=(h_0 + 1^2) \bmod m\),如果该位置仍然冲突,则尝试 \(h_2=(h_0 - 1^2) \bmod m\),接着 \(h_3=(h_0 + 2^2) \bmod m\), \(h_4=(h_0 - 2^2) \bmod m\) ,以此类推,直到找到一个空闲的位置。 ### 代码示例 以下是一个使用Python实现的平方探测散列的示例代码: ```python class HashTable: def __init__(self, size): self.size = size self.table = [None] * size def hash_function(self, key): return key % self.size def insert(self, key): index = self.hash_function(key) i = 0 while self.table[index] is not None: i += 1 if i % 2 == 1: index = (index + (i // 2 + 1) ** 2) % self.size else: index = (index - (i // 2) ** 2) % self.size self.table[index] = key def search(self, key): index = self.hash_function(key) i = 0 start_index = index while self.table[index] is not None: if self.table[index] == key: return index i += 1 if i % 2 == 1: index = (index + (i // 2 + 1) ** 2) % self.size else: index = (index - (i // 2) ** 2) % self.size if index == start_index: break return -1 # 示例使用 hash_table = HashTable(10) keys = [12, 22, 32, 42] for key in keys: hash_table.insert(key) print(hash_table.search(22)) ``` ### 应用场景 - **数据库索引**:在数据库中,为了提高数据的查询效率,常常会使用散列索引。当多个记录的关键字通过散列函数映射到同一个位置时,平方探测可以有效地处理冲突,确保每个记录都能被正确存储和快速查找。 - **缓存系统**:缓存系统需要快速地存储和查找数据。平方探测可以帮助在有限的缓存空间内处理散列冲突,提高缓存的命中率。 - **编译器符号表**:编译器在处理变量、函数等符号时,会使用符号表来记录这些符号的信息。散列技术可以加速符号的查找过程,而平方探测可以解决符号冲突问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值