《算法导论》11.3 除法散列法、乘法散列法 11.4 开放寻址法

散列函数

一、除法散列法

1、含义:通过k除以m的余数,将关键字k映射到m个槽的某一个上,即散列函数为:h(k) = k mod m,例如m = 12,所给关键字为100,则h(k) = 4。
2、在运用除法散列法的时候,要注意避免使用某些m的值,例如不推荐m=2p,因为h(k)就是k的p个最低位的数字的h,例如225mod4 = 125mod4 = 25 mod 4。
3、选一个不太接近二的整数幂的素数,是一个非常好的选择。

二、乘法散列法

1、步骤:
(1)用关键字k呈上常数A(0<A<1),并提取KA的小数部分。
(2)第二步,用m乘以这个值,然后向下取整,总之散列函数为
在这里插入图片描述
2、优点:对于m的选择并不是特别关键,一般选择它为2的某个幂次(m = 2p
在这里插入图片描述
如图,关键字k的w位表示乘上s = A*2w的w位值。在乘积的低w位中,p个最高位构成了所需的散列值h(k),在乘积的低w位中,p个最高位构成了h(k)。

开放寻址法

一、基本内容

1、基本内容:在开放寻址法中,所有元素都放在散列表里。也就是说,每个表项要么包含动态集合的一个元素,要么包含NIL。当查找某个元素的时候,要系统性检查所有表项,直到找到所需的元素,或者直到最终查明元素不再表中。
2、优势:可以将用作链接的链表存放在散列表没有用到的槽里,但是开放寻址法本身的优势就是在于它不用指针,而是计算出要存储的槽序列。于是不用指针而省下的空间可以用来提供更多槽,减少冲突。
3、探查:为了使用开放寻址法插入一个元素,需要连续地检查散列表,称为“探查(probe)”,直到找到适合的位置插入。
(1)如何探查?
我们将散列函数扩充,使之包含探查号(从零开始)以作为其第二个输入参数,这样散列函数就变为在这里插入图片描述
,对每一个关键字k,使用开放寻址法的探查序列(prove sequence)
在这里插入图片描述
这是<0,1,…m-1>的一个排列,使得每一个表位最终都有机会成为用来插入新关键字的槽。
(2)插入关键字伪代码

HASH-INSERT(T,k)
i = 0
repeat
	j = h(k,i)
	if T[j] == NIL;//如果T[j]为NIL的话,将k填入,返回位置j即可;
		T[j] = k
		return j
	else i = i+1
until i==m
error "hash table overflow"

思路:假设伪代码中散列表T的元素是无卫星数据的关键字;关键字k等同于包含关键字k的元素。每个槽包含一个关键字或NIL。
(3)查找关键字伪代码

HASH-SEARCH(T,k)
i = 0
repeat
	j = h(k,i)
	if(T[j] == k)//找到了就直接返回
		return j
	i = i+1
until T[j]==NIL or i==m	//如果T[j]=NIL就说明k不在表中,k在表中的话就得在此处
return NIL

二、线性探查和二次探查

1、线性探查

(1)给定一个普通的散列函数在这里插入图片描述
,称之为辅助散列函数线性探查方法采用的散列函数为
在这里插入图片描述
给定一个关键字k,从T[h’(k)]探查到T[m-1],再绕到T[0],T[1]直到T[h’(k)-1],所以一共有m个不容的探查序列。
(2)线性探查比较容易实现,但是容易出现一次群集的问题,因为当一个空槽之前有i个满的槽时,该槽下一个被占用的概率为(i+1)/m,连续被占用的槽会越来越多,平均查找时间也会越来越大。

二、二次探查

(1)采用如下形式的散列函数:
在这里插入图片描述
其中h’为辅助散列函数,c1和c2为正的辅助常数,i = 0,1,…m-1。初始的探查位置为T[h’(k)],后续的探查位置要加一个偏移量,该偏移量以二次的方式依赖于i。为了充分利用散列表,要限制c1c2的值;
(2)如果两个关键字的初始探查位置相同,那么它们的探查序列也相同,因为h(k1,0)=h(k2,0)蕴含h(k1,i) = h(k2,i)。这有可能造成二次群集。初始探查位置决定整个序列,有m个不同的探查序列被用到(和线性探查一样)。

三、双重散列

(1)用于开放寻址法的最好方法之一,采用如下形式散列函数:
在这里插入图片描述
h1和h2均为辅助散列函数,初始探查位置为T[h1(k)],后续加上偏移量h2(k)再模m。
(2)为了可以查找整个散列表,值h2(k)必须要和表的大小互素:第一种办法是取m为2的幂,设计一个总产生奇数的h2;第二种办法是取m为素数,并设计一个总是返回比m小的正整数的函数h2。例如,取m为素数,
在这里插入图片描述
m’略小于m。
(3)举个例子:k=123456,m=701,m’ = 700,则由h1(k)=80,h2(k)=257,可知我们第一个探查位置为80,然后检查每第257个槽,直到找到这个关键字,或者遍历完所有的槽没找到。
(4)在这里插入图片描述
图中描述的是双重散列法的插入,这里散列表的大小是13,h1(k)=k mod 13,h2(k) = 1+(k mod 11)。因为14 mod 13 = 1,14 mod 11 = 3,因此在探查了槽1和槽5后,关键字14插入到槽9中。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KeepCoding♪Toby♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值