从原理了解Hash

Hash

它是什么?

哈希表是又称散列表,一种以 “key-value” 形式存储数据的数据结构。所谓以 “key-value” 形式存储数据,是指任意的 key 都唯一对应到内存中的某个位置。只需要输入查找的值 key,就可以快速地找到其对应的 value。可以把哈希表理解为一种高级的数组,这种数组的下标可以是很大的整数,浮点数,字符串甚至结构体。

为什么存在?

有时关键码空间的数量级可能远远大于实际问题的空间,造成了巨大的浪费,我们使用桶(bucket)直接存放或间接指向一个词条。


优缺点?

优点:
>>>空间利用率 :

问题空间N,关键码空间R,桶数组(bucket array)或散列表(hash table),容量为M,则:

N < M << R

空间 = O( N + M )=O(N)

M尽可能与N同阶,所以至少与使用关键码空间相比空间利用率大大的提高了。

>>>常数级的查找时间 :

因为哈希表遵循的是循值访问,所以查找时间只需要O(1),这是再好不过的了。

缺点:
>>>冲突:

hash(key) = key % M
冲突是无法避免的,但是我们可以尽量减少冲突,并从以下两个方向入手:

  1. 精心设计散列表及散列函数,以尽可能降低冲突的概率;
  2. 制定可行的预案,以便在发生冲突时,能够尽快予以排解。

怎么用?

>>>循值访问
>>>散列函数的设计:
  • 除余法 :hash(key) = key % M

M应当选取素数。步长为step,gcd(step,M)=G,当且仅当 G == 1时,足迹能够遍布整个散列表。又由于step不能确定,所以M应是一个素数。

  • MAD法 (multiply-add-divide) :hash(key) = ( a * key + b ) % M

除余法有两个缺陷。

一:它有不动点。无论表长M取值如何,总有hash(0) ≡ 0

二:零阶均匀。[ 0 ,R)的关键码,平均分配至M个桶;但相邻的关键码的散列地址也比相邻。

取M为素数,a > 0,b > 0,a % M != 0。hash(key) = ( a * key + b ) % M

  • 平方取中 (mid-square) :取 key^2的中间若干位,构成地址

原理:将平方运算分解为一系列的左移操作,以及若干次加法,思想类似于快速幂,如13^2=13 + (13)<<2 + (13)<<3。如果忽略进位,每个数位都是由原关键码若干次求和得到的,因此两侧的数位是由更少的原数位累积而得,而越是居中的数位是由更多的原数位累积,截取居中的若干位,可以使得原关键码各数位对最终地址的影响彼此更为接近。

  • 多项式法 :
    h a s h ( s = x 0 , x 1 , x 2 , ⋅ ⋅ ⋅ , x n − 1 ) = x 0 ∗ a n − 1 + x 1 ∗ a n − 2 + ⋅ ⋅ ⋅ + x n − 2 ∗ a 1 + x n − 1 hash( s = x_0,x_1,x_2,···,x_{n-1} ) = x_0*a^{n-1} + x_1*a^{n-2} + ··· + x_{n-2}*a^1 + x_{n-1} hash(s=x0x1x2x

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值