【算法笔记】哈希hash

1.哈希hash引入

小集合元素M在大集合N中的出现次数。

如果二重循环遍历,时间复杂度O(NM),N、M大时很大

用空间换时间:

一个bool型数组hashTable[MAX](若需要出现次数则换成int)

用此数组值标记是否出现过(数组读入时):hashTable[x]=true;……………………O(N)

输出出现过的元素:判断是否true……………………………………………………O(M)

总时间复杂度O(M+N)

方法:直接把输入的数作为数组的下标X来对这个数的性质进行统计

但是,上面的输入的数每一个都是不超过10^5的整数,如果需要统计的是一个巨大的数,甚至是一个有意义的字符串,(字符串和极大数)无法记为下标

我们希望将需要统计的元素转化为可以唯一标识的较小整数,就可以通过下标计数了

即由key->H(key),key值变为其单值函数值,将单值函数值作为数组下标

2.常见hash函数:

直接定址法,除留余数法,平方取中法(少用)

1)直接定址法->恒等变换

H(key)=key

H(key)=a*key+b

2)除留余数法

H(key)=key%mod

通过此法,可以将key转换为不超过mod的整数,这样就可以将它作为数组下标。

/*注意表长TSize(即下标最大值)必须不小于mod,否则会产生越界。

当mod为素数,H(key)能尽可能覆盖[0,mod)内每一个数。*/

一般为了方便,TSize取为素数,mod取为等于mod

显然,通过%mod方法,可能会存在H(key)相同,但原本key值不同的情况——称为“冲突”

##解决冲突的方法:

——1开放定址法(线性探查法、平方探查法) 计算新的hash值

*线性探查法:

当得到key的hash值H(key),但是表中下标为H(key)已被占用时,

检查H(key)+1是否被占,直到探查到未被占的位置。

如果检查过程超过了表长,则回到表头,直到找到一个可使用的位置或者发现表已经被占满。

缺点:易导致扎堆,即表中连续若干个位置都被使用,这在一定程度上会降低效率。

*平方探查法:

为避免扎堆现象,

依次检查H(Key)+1²、H(Key)-1²、H(Key)+2²、H(Key)-2²…………

如果过程中H(key)+k²超过了表长,则将其对表长取模,

如果过程中H(key)-k²<0(假设首位为0),则取

((H(key)-k²)  % TSize + TSize)%TSize   

为了避免负数的麻烦,可以只进行正向的平方探查。

——2拉链法

不用重新计算新的hash值,而是把所有H(key)相同的key连接成一条单链表

一般来说,可以使用标准库模板库中的map来直接使用hash的功能(C++11以后可以用unordered_map速度更快)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值