散列表(Hash)-复习

1.定义

一般来说,散列可以浓缩成一句话“将元素通过一个函数转换为整数,使得该整数可以唯一的代表这个元素。”其中把这个转换函数称为散列函数H,也就是说,如果元素在转换前为key,那么转换后就是一个整数H(key)。

那么对于key是整数的情况来说,有哪些常用的散列函数呢?一般来说有以下几种:

①直接定址法:即恒等变换(即H(key)=key)

②线性变换法:即H(key)=a*key+b;

③平方取中法(很少用):取key的平方的中间若干位作为hash值。

④除留余数法:把key除以一个数mod得到的余数作为hash值的方法:H(key)=key%mod

通过这个散列函数,可以把很大的数转换为不超过mod的整数,这样就可以将它作为可行的数组下标。显然当mod是一个素数时,H(key)能尽可能的覆盖[0,mod)范围内的每一个数。

2.冲突及解决办法

但是除留余数法可能会有两个不同的数key1和key2,它们的hash值是相同的。key2不再能使用这个位置了,便冲突。

解决冲突的办法大致有三种:

2.1 线性探查法(Linear Probing)

当得到key的hash值H(key),但是表中下标为H(key)的位置已经被某个其他元素使用了,那么就检查下一个位置H(key)+1是否被占用,如果没有,就使用这个位置;否则就继续检查下一个位置(也就是hash值不断加1)。

如果检查过程中超过了表长,那么就回到表的首位继续循环,直到找到一个可以使用的位置,或者是发现表中所有位置都已被使用。

显然,这个做法容易导致扎堆,即表中利纳许若干个位置都被使用,这代一定程度上会降低效率。

2.2 平方探测法(Quadratic probing)

避免扎堆现象,按下面的顺序:

如果H(key)+k^2 超过了表长TSize,那么就把 H(key)+k^2 对表长TSize取模;

如果H(key)+k^2<0,那么将(H(key)+k^2)%TSize + TSize)%TSize作为结果(等价于将H(Key)-k^2不断加上一个TSize直到出现一个非负数)。

2.3 链地址法(拉链法)

和上面两种方法不同,链地址法不计算新的hash值,而是把所有的H(key)相同的key连接成一条单链表

这样可以设定一个数组Link,范围是Link[0]~Link[mod],其中Link[h]存放H(Key)=h的一条单链表,于是当多个关键字key的hash都是h时,就可以直接把这些冲突的key直。

 接用单链表连接起来,此时就可以遍历这条单链表来寻找所有的H(key)=h的key。

2.4 双散列法

需要使用两个散列函数,当通过第一个散列函数H1(key)得到的地址发生冲突时,则利用第二个散列函数H2(key)计算该关键字的地址增量。它的具体散列函数形式如下:

H_1=(H(key)+i*Hash_2(key))%m

初始探测位置 H_0=H(key)%m。 其中i是冲突的次数, 初始为0。在双散列法中,最多经过m-1次探测就会遍历表中的所有位置,回到H_0位置。 

3.散列查找及性能分析

这里不多赘述了,比较简单,贴上图

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值