哈希结构介绍及实现(线性探测)——闭散列解决哈希冲突

哈希介绍

顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经 过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O( logN),搜索的效率取决 于搜索过程中元素的比较次数。
理想的搜索方法:可以不经过任何比较,一次直接从表中得到要搜索的元素。 如果构造一种存储结构,通过 某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函 数可以很快找到该元素。
插入元素 :根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放
搜索元素 :对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比 较,若关键码相等,则搜索成功
例如 数据集合{1,7,6,4,5,9};
哈希函数设置为:hash(key) = key % capacity; capacity为存储元素底层空间总的大小。

在这里插入图片描述
这样的好处是查询时只需要带入这个哈希函数中即可判断出该数据是否存在,但是,如果现在要插入14这个元素,便会出现冲突,这便引出了哈希冲突

哈希冲突

不同关键字通过 相同哈希哈数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。
引起哈希冲突的一个原因可能是:哈希函数设计不够合理
哈希函数设计原则:
1.哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值域必须在0 到m-1之间
2.哈希函数计算出来的地址能均匀分布在整个空间中
3.哈希函数应该比较简单
常用的哈希函数设计方式
1.直接定制法
取关键字的某个线性函数为散列地址**:Hash(Key)= A*Key + B** 优点:简单、均匀 缺点:需要事先 知道关键字的分布情况
使用场景:适合查找比较小且连续的情况
2.除留余数法
设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函 数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址
3.平方取中法
假设关键字为1234,对它平方就是1522756,抽取中间的3位227作为哈希地址; 再比如关键字为 4321,对它平方就是18671041,抽取中间的3位671(或710)作为哈希地址
平方取中法比较适合:不知道关键字的分布,而位数又不是很大的情况
4.折叠法
折叠法是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加 求和,并按散列表表长,取后几位作为散列地址。
折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况
5.随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key) = random(key),其中random为 随机数函数。
通常应用于关键字长度不等时采用此法

注意:当哈希函数设计的越巧妙,越精准,则产生冲突的可能性就会减少很多,但是冲突是不可避免的

哈希冲突的解决

解决哈希冲突的常见方法有:开散列,闭散列。
闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那 么可以把key存放到冲突位置中的“下一个” 空位置中去。
1.线性探测(主讲):从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。
比如上述的例子中,如果要插入44这个元素,通过哈希函数算出其地址为4,但是地址4这个地方已经存在元素4了,即发生了哈希冲突,那么此时就向后寻找第一个空位置,即地址为8的这个地方
在这里插入图片描述
删除
采用闭散列解决哈希冲突时,不能直接物理删除哈希表中已经存在的元素,否则会影响其它元素的查询,比如还是上述例子中,如果将哈希表中的元素4直接删除,则地址为4的这个地方为空,如果查找44这个元素,根据哈希函数算出来的地址为4,此时法相为空,则表示44不在这个哈希表中,可实际上44存在于这个哈希表中。
所以这里的删除需要用到一个标记来进行伪删除

现性探测的实现

#include <iostream>
#include <vector>
using namespace std;
//删除标记
enum State
{
   
	EMPTY,//表示该位置为空
	EXIST,//表示存在
	DELETE//表示删除即伪删除
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值