哈希表构建&哈希冲突解决

一、构造哈希表的几种方法

1.1 直接定址法

f(key) = a × key + b

1.2 除留余数法

f( key ) = key mod p ( p ≤ m )

mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可在折叠、平方取中后再取模。

  1. 直接定址法(取关键字的某个线性函数为哈希地址)
  2. 除留取余法(取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址)
  3. 平方取中法
  4. 折叠法
  5. 随机数法
  6. 数学分析法
    常用方法是 直接定址法除留余数法

二、哈希冲突(碰撞)以及处理

不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突。任意的散列函数都不能避免产生冲突。

2.1 开发定址法

所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。主要有以下几种:

2.1.1 线性探测法

f ( k e y ) = ( f ( k e y ) + d i ) M O D m ( d i = 1 , 2 , 3 , . . . . . . , m − 1 ) f(key) = (f(key)+di) MOD m (di=1,2,3,......,m-1) f(key)=(f(key)+di)MODm(di=1,2,3,......,m1)

用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探测到开放的地址则表明表中无待查的关键字,即查找失败。

2.1.2 二次探测法

f ( k e y ) = ( f ( k e y ) + d i ) M O D m ( d i = 1 2 , − 1 2 , 2 2 , − 2 2 , … … , q 2 , − q 2 , q < = m / 2 ) f(key) = (f(key)+di) MOD m (di = 1^2, -1^2, 2^2, -2^2,……, q^2, -q^2, q <= m/2) f(key)=(f(key)+di)MODm(di=12,12,22,22,,q2,q2,q<=m/2)

注:1^2 表示是 1的平方

即:
key1:hash(key)+0
key2:hash(key)+1^2
key3:hash(key)+2^2

设哈希表长m=14,哈希函数 H ( k e y ) = k e y % 11 H(key)=key%11 Hkeykey11。表中已有4个结点:addr(15)=4,addr(38)=5,addr(61)=6,addr(84)=7,其余地址为空。如果用二次探测再散列处理冲突,关键字为49的结点的地址是?

因为 f(49) = 5 与 f(38) 冲突
所以需要采用二次探测再散列来处理冲突
(f(49) + di) MOD 14(哈希表长m=14)

第一次 di = 1^2
(5 + 1)MOD 14 = 6 与addr(61)=6冲突
第二次 di = -1^2
(5 - 1)MOD 14 = 4 与addr(15)=4 冲突
第三次 di = 2^2
(5 + 4)MOD 14 = 9 没有冲突
所以 addr(49)=9

此方法有如下几条定律:
H a s h ( i ) = H a s h ( 0 ) + i 2 Hash(i) = Hash(0) + i^2 Hash(i)=Hash(0)+i2
H a s h ( i ) = H a s h ( 0 ) + ( i − 1 ) 2 Hash(i) = Hash(0) + (i-1)^2 Hash(i)=Hash(0)+(i1)2
H a s h ( i ) = H a s h ( i − 1 ) + ( 2 i − i ) Hash(i) = Hash(i-1) + (2i-i) Hash(i)=Hash(i1)+(2ii)

2.2 链地址法

前面我们谈到了散列冲突处理的开放定址法,它的思路就是一旦发生了冲突,就去寻找下一个空的散列地址。那么,有冲突就非要换地方呢,我们直接就在原地处理行不行呢?
答案是可以的,就是链地址法,就好比Java里的HashMap的数据结构一样。

参考链接:
https://www.jianshu.com/p/585f8882bbfb
https://blog.csdn.net/xyzbaihaiping/article/details/51607770

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值