散列(哈希表):
更好的去查找一个元素,直接知道其存储位置
散列本质就是一个函数,给定值之后返回其对应的地址
1,散列函数:
➢ 散列函数:把关键词值映射到散列地址,通常用h来表示。
➢ h(Key) =Address of Hash Table
➢ 散列函数的选取原则
✓便于快速计算
✓极少出现冲突:不同关键词的散列函数值尽可能不同
⚫ 函数值域在散列表长范围内,即0 £ h(K) < M, M为散列表长度。
⚫ 关键词映射到散列表各位置的概率尽量相等,使散列函数值在
区间 [0,M-1] 内均匀分布。
1,取余法:
h(K) = K%M。其中M为散列表长度, %为取余运算,也表示为mod。
如果是等差数列,只有当等差和M互质,才有可能均匀分布
2,MAD法
h(K) = (a´K+b)%M ,M为素数,a>1,b>1,m和a互质
3,乘法散列表:h(k)=M((k*x )mod 1)
即用M*(k*x的小数部分)来确定位置.一般这里的x为黄金分割点的值0.618
4,平方取中值
5,压缩法
5.1异或和来压缩
缺点是ab和ba值一样,而且baab cccc都是一个地址
5.2折叠法
对字串进行求和
6.抽取法取特定的某几位当作地址
➢ 函数值仅依赖关键词的部分位, 而不是依赖整个关键词,容易出现冲
突,如 h(THE)=h(FROM)=h(ONE)=h(WE) =(101)2 = 5,
h(1234567)= h(1639527)= h(1536517)=1357
2.冲突的解决办法:
2.1(开散列法)拉链法:
利用链表实现
2.2闭散列表
2.2.1线性探查:
➢当发生冲突时,以固定的次序查找表中的记录,直到找到一个关键词为K的结点或者找到一个空位置
➢ 其循环探查路径: hi = ( h(K) + i ) % M
h(K), h(K)+1, h(K)+2, h(K)+3, …, M-1, 0, 1, …, h(K)-1
➢ 检查相邻元素,缓存命中率高。
缺点:容易出现聚集现象,即所有的都杂糅在了一起
装填因子:a=N/M 其中a最好在0.5--0.8,也就是说最好装一半到80%
成功查找长度:查找次数之和/元素个数
失败查找长度:M个元素查找到失败的次数/M 注意:到空位才失败
成功平均查找长度:(1+1+1+1+3+1+1+3)/8
失败平均查找长度:(6+5+4+3+2+1+4+3+2+1)/10
现有长度为11且初始为空的散列表HT,散列函数是H(K)=K%7,采用线性探查法解决冲突。将关键词序列87, 40, 30, 6, 11, 22, 98, 20依次插入HT后,HT查找失败的平均查找长度是_____. 【2019年考研题全国卷】
A.4 B.5.25 C.6 D.6.29
ASL=(9+ 8+ 7+ 6+ 5+ 4+ 3 ) /7= 42/7= 6
2.2二次探查
探测序列:hi = (h(K) ±i^2 ) % M ,其中i=1, 2, …, (M-1)/2, M为散列表长
特点:一旦冲突,能更快的跳离“是非之地”,避免聚集
2.3双重探查
从h(K)开始,寻找空地址时,所前进的步长不是固定的,而与K有关,即用δ(K)代替线性探查的前进步长1 (1≤ δ(K) <M) 。
➢ 循环探查路径:
h(K), h(K)+ δ(K), h(K)+ 2δ(K), …以上各值均在 % M意义下
➢ 为了确保表中的每一个地址都能探查到,要求δ(K)和M互质,因此M应选作素数。
3.散列表的删除
如果是拉链法,可以直接使用链表的删除
如果是线性探查法,不可以直接删除,会导致断层
1,懒惰删除,
表示该处为已删除,继续向后寻找,如果在插入的时候也可以在这个地方插入
缺点:会使查找的次数变多
2,实时删除
删除T[j]:将位置j清空,然后考察位置j+1到下一个空位前的每一个位置i,看将位置j清空后,是否阻碍查找T[i]的探查路径,若是则将T[i]前移至空位。
如下面M=13的,h[k]=k%13,删除9
当装填因子<=2/3,平均时间复杂度为O(1)。
3,延迟删除
✓可以保存每一个元素的访问次数。
✓将标记为“已删除”的位置清空,然后把元素按访问次数递减的顺序依次重新插入散列表,使被频繁访问的元素存储在接近其散列函数值的位置,有利于减少平均查找长度。