散列学习(一)

散列(一)
1、使用步骤:
     1)、用散列函数将键转化为数组的索引。
     2)、处理碰撞冲突过程。
2、散列函数:
如果一个数组可以保存M个键值对,那么需要一个能够将任意键转化为该数组范围内的索引的散列函数。该散列函数应易于计算并能够均匀分布在所有的键。
散列函数与键的类型有关。对于每种类型的键都需要一个与之对应的散列函数。
1)、正整数
整数散列最常用的方法是除留余数法。使用大小为素数M的数组。
2)、浮点数
如果是0到1之间的实数,可以将它乘以M并四舍五入得到一个0至M-1之间的索引值。
缺点:键的高位起的作用更大,最低位对散列结果没有影响。
解决方法:将键表示为二进制数然后再使用除留余数法。
3)、字符串
将字符串当做大整数,使用除留余数法计算散列值。
Int hash = 0;
for(int I = 0; I < s.length(); i++)
    hash = (R*hash + s.charAt(i))%M;
如果R比任何字符的值都大,上述运算相当于将字符串当做一个N位的R进制值,将它除以M并取余。
R要足够小,不造成溢出,结果就能如我们所愿。
经典的Horner方法:用N次乘法、加法和取余来计算一个字符串的散列值。
Horner方法:至多做n次乘法和n次加法就能计算出一个n次多项式的值。
4)、组合键:
如果键的类型含有多个整形变量,可以和字符串类型一样将他们混合起来。
如键的类型是Date可以这样计算散列:
int hash = (((day * R +month)%M)*R +year)%M;
3、软缓存:
如果散列值的计算很耗时,那么我们可以将每个键的散列值缓存起来,即在每个建中使用一个hash变量来保存它的散列值。第一次调用计算散列值的函数时,需要计算该对象的散列值,之后对计算散列值函数的调用会直接返回hash变量的值。
总体来书,要为一个数据类型实现一个优秀的散列方法,需满足三个条件:
一致性:等价的键必然产生相等的散列值;
高效性:计算简便;
均匀性:均匀的散列所有的键。
在有性能要求时,应谨慎使用散列,糟糕的散列函数经常是性能问题的罪魁祸首。保证均匀性的最好办法也许就是保证键的每一位都在散列值的计算中起到了相同的作用;实现三类函数最常见的错误也许就是忽略了键的高位。无论散列函数的实现是什么,当性能很重要时,你应该测试所使用的散列函数。
计算散列函数和比较两个键哪个耗时更多?
你的散列函数能够将一组键均匀的散布在0到M-1之间吗?
用简单的实现测试这些问题能预防未来的悲剧。
这些讨论基于使用散列时的一个重要假设(是一个实际上无法达到的理想模型,但是实现散列函数时的知道思想):
假设J(均匀散列假设):使用的散列函数能均匀并独立地将所有的键散布于0到M-1之间。
讨论:实现散列函数时随意指定了很多参数,显然无法实现一个能在数学意义上均匀并独立地散步所有键的散列函数。要找到一个计算简单又拥有均一性和独立性的散列函数是不太可能的。实际中,如同随机数生成函数random()一样,大多数程序员都会实现与随机数生成器函数很相似的散列函数。很少有人回去验证独立性,这一点一般都不会满足。
假设J提供给我们考察散列函数的重要方式:
1)、设计散列函数时应尽量避免随意指定参数来防止大量的碰撞。
2)、使用数学分析来预测散列算法的性能并在实验中进行验证。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值