散列表的删除与冲突处理 - 平方探测

本文探讨了散列表中的冲突处理方法——平方探测,解释了其工作原理及可能遇到的问题。当散列表长度为4K+3形式的素数时,平方探测法能探测到所有空间。此外,介绍了如何实现平方探测的插入操作,以及散列表的“懒惰删除”方法,以防止查找过程中的“断链”问题。完整的代码实现可在GitHub上查看。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接下来我们看冲突处理中的平方探测法(终于写出来了- -、),平方探测顾名思义就是探测增量是1²、-1²、2²、-2²…(线性探测是1、2、3、4……),平方探测与线性探测有点不同,线性探测是查找位置发生冲突后,就往后探测,后一个位置又有冲突的话,继续往后探测,直到找到空位置为止,所以说只要散列表上有空的单元格,线性探测就一定可以找到空位置。但是平方探测不一定,平方探测的做法是:查找某个位置,如果发现冲突了,先往后探测,就是往1²探测,如果1²位置也有冲突,就往前探测,探测-1²的位置,如果-1²位置为空就插入,不为空也就是有冲突就向2²位置探测,接着是-2²、3²、-3²……这样的平方探测法,是不是散列表中有空位就一定能够探测出来呢?我们看一个例子:

散列表的最大长度为5,表中已存在元素3个,假如此时插入了一个元素21,会出现什么样的情况?21对5求余得1,散列表上1这个位置已经有元素了,那么按照平方探测法就会去探测原来位置+1²这个位置(也就是散列地址为2),2这个位置有12这个元素了,接着往-1²位置,也就是下标为0的位置上,发现还有元素,再往2²位置探测,这时我们看,初始的散列位置1+2²等于散列地址为0这个位置,发现回到之前探测过的位置了,这个位置不行,就到-2²探测,等于又回到2这个位置。。。。你可以亲自验证一下,3²也是这样,4²也是这样,就是出现一种什么样的情况呢,散列表中是有空位置的,但就是一直查找不出来,这就很尴尬了。平方探测法的存在一定是有它的理由的,它的优点在于减轻线性探测的“聚集”现象(就是很多元素在相邻的散列地址上“堆积”了起来,这样会大大降低查找效率)。

      怎么办?看书上说:“有证明表示,如果散列表长度是某个4K+3(K是正整数)形式的素数时,平方探测法就可以探测到整个散列表的空间。这一点很重要,是我们能够放心使用平方探测法的理论保证。”

      好啦,

二次探测解决冲突散列表可以通过以下步骤来实现: 1. 创建一个散列表,其中包含一个固定大小的数组和一个用于存储键值对的结构。 2. 定义一个哈希函数,将键映射到数组的索引位置。这个哈希函数可以是任何将键转换为整数的算法。 3. 当插入一个新的键值对时,首先使用哈希函数计算键的索引位置。如果该位置为空,则直接将键值对存储在该位置。 4. 如果该位置已经被占用,则使用二次探测来寻找下一个可用的位置。二次探测是指在散列表中按照一定的步长进行探测,直到找到一个空位置或者遍历完整个散列表。 5. 为了实现二次探测,可以定义一个步长函数,根据当前探测的次数来计算下一个探测的位置。常见的步长函数包括线性探测平方探测和双散列等。 6. 重复步骤4和步骤5,直到找到一个空位置,然后将键值对存储在该位置。 7. 当查找一个键时,使用相同的哈希函数计算键的索引位置。如果该位置为空,则说明键不存在于散列表中。 8. 如果该位置不为空,则比较键的值存储在该位置的键的值。如果它们相等,则找到了目标键。 9. 如果它们不相等,则使用相同的步长函数来继续探测下一个位置,直到找到目标键或者遍历完整个散列表。 10. 如果遍历完整个散列表仍然没有找到目标键,则说明目标键不存在于散列表中。 下面是一个使用二次探测解决冲突散列表的示例代码: ```python class HashTable: def __init__(self, size): self.size = size self.table = [None] * size def hash_function(self, key): return hash(key) % self.size def insert(self, key, value): index = self.hash_function(key) if self.table[index] is None: self.table[index] = (key, value) else: step = 1 while True: new_index = (index + step**2) % self.size if self.table[new_index] is None: self.table[new_index] = (key, value) break step += 1 def search(self, key): index = self.hash_function(key) if self.table[index] is None: return None elif self.table[index][0] == key: return self.table[index][1] else: step = 1 while True: new_index = (index + step**2) % self.size if self.table[new_index] is None: return None elif self.table[new_index][0] == key: return self.table[new_index][1] step += 1 # 创建一个大小为10的散列表 hash_table = HashTable(10) # 插入键值对 hash_table.insert('apple', 5) hash_table.insert('banana', 10) hash_table.insert('orange', 15) # 查找键的值 print(hash_table.search('apple')) # 输出:5 print(hash_table.search('banana')) # 输出:10 print(hash_table.search('orange')) # 输出:15 print(hash_table.search('grape')) # 输出:None ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值