几种常见散列方法

常见散列方法

1.取余法:hash(Key)=Key%M。其中M的取值有技巧。M首先尽量不能选取较为规整的数字,如2的n次方,这样是很容易出现分布不均匀的情况,也就是很容易出现散列冲突,散列的意义就变小了。那么我们一般选取一个合适的素数M来作为余数。个人理解:很多个数余上同一个数M,会冲突是几乎没办法的事情,但是如果能让某一类的数都不可能发生冲突那么就很好了。那么假设数S,gcd(S,M)一定是为1的,根据数论或者可以自己理解的话我们可以知道,KS(K为整数)在M个位置还没被填满之前是不可能发生冲突的。也就是只要是S的倍数都不可能在同一个位置上,我们还可以画一个范围是M的数轴把S当作一个周期,KS当作一个个周期往后走来理解。所以这样S的倍数全都不可能冲突,而离的比较近的数S1,S2,余上同一个数会相同的概率也很小。所以整体来说减少了很多冲突的机会,所以用合适的素数作为M是很合适的。
2.MAD法: 除余法的改进,让散列有更高阶的均匀性。取M为素数,a>0,b>0,a%M!=0,hash(Key)=(a*Key+b)%M。视具体情况所定,有时候并不需要更高阶的均匀性。
3.平方去中法:Key平方后,取中间的几位作为散列地址。为何取中?平方可以看成位移后相加的操作,平方后的数的中间几位,是由Key的更多数位相加构成的,具有更多Key的特性,两侧则相反。所以平方后取中可以尽可能体现Key的特性,使得分布减少冲突。
4.折叠法:将Key折叠切割,如123456789可以将其地址转换为123+456+789=1368。当然还有更多的折叠方式,具体视情况而定。
5.伪随机数法: hash(Key)=rand(Key)=【rand(0)pow(a,Key)】%M。(伪)随机数发生器的实现,因具体平台,不同历史版本而异创建的散列表可移植性差,慎用
总之,散列函数,越是随机,越是没有规律,越好。
6.字符串转化法(多项式法):有时候Key可能是一个字符串,用其来表示Key需要进行转化。如多项式法,把每个字符转化为数字,作为x0,x1,x2…xn,再确定一个常数a,求x
pow(a,k)(0<=k<=n-1)的和,也就是多项式的和。那么我们再做两件事,加快多项式计算,就用秦九韶算法,再模仿这一算法,进行一个与多项式计算近似的一个运算。

int hashcode(char s[])
{
    int h=0;
    for(int strlen(s),i=0;i<n;++i){
        h=(h<<5|h>>27);
        h+=(int)s[i];}
    return h;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值