研究散列(Hashing)算法的体会

 

散列,虽然只支持二叉查找树所允许的一部分操作,但是散列具有以常数平均时间执行插入、删除和查找的特点。

散列无法有效支持元素间排序的操作,因此像findMaxfindMin以及在线性时间内按顺序打印所有元素的操作都无法支持。

为了解决散列冲突问题,普遍存在两种方式,

一、分离链接法(separate chaining),其做法是将散列到同一个位置的元素以一个链表的方式保存。通常产生冲突的元素被插入到链表的最前面,这样不仅方便,而且由于最后插入的元素最有可能不久再使用,这样在查找起来效率会增加。分离链接实现简单,但是双向链表会占用额外的内存,冲突严重时,查找效率也会严重下降。

二、探测散列表(probing hash tables),其做法是发生冲突时,尝试使用其他的单元,知道找到空闲的单元为止。因为要确保所有的元素都能插入到表中,所需要的表要比分离链接法的表大,其装填因子应该低于λ=0.5

探测散列表又有三种解决冲突的方法,一种是线性探测,即逐个探测f(i)=i。优点是算法简单,缺点是存在“一次聚集”问题(Primary Clustering)。另一种是平方探测,即f(i)=i2。对于平方探测,表的大小是素数,那么当表至少有一半是空的时候,总能插入一个新的元素。虽然平方探测排除了一次聚集,但是散列到同一位置上的那些元素将探测相同的备选单元,即“二次聚集”(Secondary Clustering)。最后一种是双散列(double hashing),一种流行的选择是f(i)=i*hash2(x)。这个公式表明需要用到第二个散列函数用来解决冲突。诸如hash2(x)=R-(x mod R)R是小于TableSize的素数这样的函数将起到良好的作用,它可以尽可能做到在第一次散列到同样单元的元素,第二次散列到不同的其他元素上,即使会发生最坏的情况,但是非常少。

 

研究散列算法让我联系到另外一个应用,就是产生不重复的随机数,例如卡管理系统。都需要产生不规则的随机数作为卡号或密码,记得遇到一个类似的系统是通过产生可以重复的随机数(20位左右),利用数据库唯一索引检查,避免出现重复。不过运行时间长后,由于数据量越来越大,执行效率低的可怕。现在想起来,其实就是一个解决插入冲突的问题,分段的hashing算法就是一个解决办法不是。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值