HASH
2021.5.7修改
2021.8.10修改
hash这个东西我们早就接触过,研究过,但是不能理解。所以我今天抽出来足够的时间来学习。
我们做题的过程中,通常会对线性表进行查找操作,顺序查找就依次遍历是否相等,直到相等然后返回索引;在有序中我们就通过二分查找
那么我们能不能不经过比较,直接通过关键字key一次得到索要结果?这时就有了hash
1.何为hash
使用一个哈希函数将某一个特定的数字变成另一个数字,这个操作就叫hash
通常我们用取余表示哈希函数
要说hash,我们必须了解一种存储方式,散列方式
散列方式,是指在记录的存储位置和他的关键字之间建立一个对应关系,使每一个关键字都对应一个存储位置,这样在查找的过程中,只需要通过这个关系给key进行映射。最后我们把这种对应关系称为散列函数或者哈希函数
按照这个思想,采用散列方式记录存储一块连续的存储空间,这个空间称之为哈希表。
其实这些都是一些官方话,我个人理解的hash其实就是我们在查询的时候,需要把一个关键值进行一系列的操作变成一个新值然后把新值存储在一个空间里面,这个新值叫做hash值,空间叫做hash表
hash就是在MLE的边缘徘徊,自然溢出是很正常的,如果用unsigned long long类型的就可以自动解决溢出的情况,相当于自动对264取模,真好
还可以提高正确率
2.hash查找顺序
(1)存储数据,将数据存入哈希函数计算所得那个地址里面
(2)查找时,使用同一个hash函数通过key计算地址,通过该地址即可访问到查找的记录
3.hash冲突
再美好的情况下,每一个关键字通过hash计算出来的地址都是不一样的,但是实际情况中,我们常常会碰见f (k1)=f(k2)的情况,这种情况叫冲突
当然哈希是不可避免的,但是算一下概率,一般不恶心的题都够用
k1和k2是这个函数的同义词
冲突会造成错误,具体的解决冲突的方法我们后面会提到
4.hash函数的构造
(1)原则
①计算简单
②散列地址均匀,防止冲突
(2)构造方法
①直接定址
取关键字或关键字的线性函数值为hash地址,即:hash(k)=k或hash(k)=a*k+b
优点,简单均匀,不产生冲突
缺点,适合hash表比较小并且连续的情况
②数字分析
数字分析法使用关键字位数比较多的数字,通过抽取关键字的一部分进行操作,计算hash存储位置的方法。这种方法实现得知道关键字的分布且关键字的若干位分布均匀。
比如我们说的手机号,手机号的后四位是一定的,不能变的,身份证的后四位也是唯一的,我们就可以用这种方法做hash函数的取值
③平方取中
具体方法很简单,先对关键字进行取平方,然后中间几位为hash地址,适用于不知道关键字的分布而且位数不大的情况
中间几位所取的hash值然后取中间位的话会过于庞大,占空间的代价不想而知,所以我们可以在进行/10 ,/100等操作进行降低空间
④折叠法
之前所整理的全是一些官方话
这样的方法就是当数特别大的时候可以将其分位,对每一位奇数偶数位对调,这样的瞎折腾其实就是为了防止冲突
⑤取余数法
这个方法最常用了,对与长度为m的hash公式为f(k)=k%p
这个方法不仅可以对关键字进行直接取模,也可以在折叠平方取中之后再取模
所以这个p的选择很重要,选择不好就会发现冲突,根据前人经验:若散列表的长度为m,通常p为小于等于表长的最小质数或者不包含小于20质因子的合数,或者一般都取100000003
int hash(int num)//取余求值 线性探索
{
int tmp;
tmp=num%MOD;//取余法
while(1)
{
if(hashs[tmp]==-1)//当前位置为空
{
hashh[tmp]=num;
break;
}
else
tmp=(tmp+1)%MOD;//线性探索
]
}
⑥ 随机取数
这个方法用随机函数作为函数值,比较简单好想。
5.解决hash冲突
冲突的定义我们在前文已经提到,这里说明如何解决冲突
①线性探测
线性探测就是说当hash值发生冲突的时候,如果这个位置已经有数据,那么就用线线性的方法找一个空的位置,找到了空的就放进去,其实这种方法就是把hash表看成一个环形结构
②平方探测
其实这种方法,原理和线性探测差不多,只是说线性探测是一个一个测,那么不下降成了线性查找了?所以我们只需要平方的步数前后尝试即可
③再hash
字面意思就是说再来一个hash,就是说一开始的时候设置好几个hash函数,如果第一个冲突了那就用第二个,第二个冲突了那就用第三个…
④链表
用链表来存储hash值而不是使用数组,这样发生冲突了直接存在链表后面
也就是将发生冲突的数串成一链,这种方法得使用取余法,取余的余数冲突了,才存在一链上面
本文深入探讨了哈希(Hash)的概念及其在数据查找中的作用,包括哈希函数的构造方法如直接定址、数字分析、平方取中、折叠法和取余数法。还讨论了哈希冲突的常见现象及解决策略,如线性探测、平方探测、再哈希和链表法。重点介绍了哈希函数的设计原则,旨在提高查找效率并减少冲突。
10万+

被折叠的 条评论
为什么被折叠?



