散列表(hash)是什么?
散列技术实在记录的存储位置和它的关键字之间建立一个确定的对应关系f,是的每个关键字key对应一个存储位置f(key)。
我们把这种对应关系f称为散列函数,又称为哈希函数。按这个思路,采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或者哈希表。那么关键字对应的记录存储位置我们称为散列地址。
散列技术最适合的求解问题是查找与给定值相等的记录。对于查找来说,简化了比较过程,效率就会大大提高。
我们时常会碰到两个关键字key1,key2,但是f(key1)!=f(key2),这种现象我们称之为冲突,并把key1和key2称为散列函数的同义词。
如何构造散列表?
- 直接定址法
我们去关键字的某个线性函数值为散列地址。即:f(key)=a*key+b(a、b为常数)。
这样的散列函数优点就是简单、均匀,也不会产生冲突。但问题是这需要事先知道关键字的分布取情况,适合查找表较小且连续的情况。由于这样的限制,在现实应用中,此方法虽然简单,但却不常用。
数字分析法
抽取部分关键字,如手机号后4位作为hash值。这种方法适用于事先知道关键字分布的若干位比较均匀的情况。平方取中法·
这方法相对简单,只是把key值做平方后取中间某几位。折叠法
将关键字从左到右分成几部分,将这几部分相加后取其中几位数作为散列地址。除留余数法
这种方法最常用。公式为f(key)=key mod p(p<=m),mod是取模(求余数)的意思。实际上,这方法不仅可以对关键字直接取模,也可以折叠、平方后取中再取模。
显然,本方法关键就在于选取核实的p,p如果选的不好,就容易产生同义词。
根据经验,若散列表长为m,通常p为小于或等于表长的最小指数或不包含小于20质因子的合数。
如何处理散列表冲突?
开放定址法
一旦发生冲突,就去找下一个空的散列地址。只要散列表足够大,空的散列地址总能找到,并将记录存入到该地址下。再散列函数法
对于我们的散列表来说,我们准备多个散列函数,f(key)=RH(key),这里RH就是不同的散列函数,可以把之前说的除留余数、折叠、平方取中全部用上,每当发生冲突时,就换一个散列函数计算,相信总有一个散列函数能把冲突解决掉。这种方法能够是关键字不聚集,但也相应的增加了计算的时间。链地址法
在散列表中增加单链表,产生冲突即在当前位置给单链表增加节点,这样保证了绝对不会出现找不到地址的情况出现,但是也带来了查找时需要遍历单链表的性能损耗。公共区溢出法
为所有冲突的关键字简历一个公共溢出区存放。在查找时,咸鱼基本表相应位置进行对比,如果相等则查找成功,如果不相等则到溢出表去进行顺序查找,相对基本表而言,有冲突的数据很少的情况下,公共溢出区的结构对查找性能来说还是非常高的。
散列表查找如何实现?
1.定义散列表结构并初始化散列表
2.定义散列函数
3.插入散列表:插入关键字时,先算出散列地址,如果当前地址部位空关键字,则说明有冲突,此时使用适当方法解决冲突
4.通过散列表查找
什么是哈希算法?
就是以较短的信息来保证文件唯一性的标志,这种标志与文件的每一个字节相关,而且难以找到逆向规律。
哈希算法的应用场景?
版本控制
网络部署和版本控制工具使用hash算法,保证文件的可靠性(当原有文件发生改变时,其标志值也会发生改变,从而告诉文件使用者当前的文件已经不是所需的文件)安全加密
给证书、文档密码登高安全系数的内容添加加密保护(不可逆性)
哈希算法的特点?
正向快速
给定铭文和hash算法,有限时间和有限资源内能计算出hash值逆向困难
给定若干hash值,有限时间内很难逆推明文输入敏感
原始输入有一点裱花,输出差异会非常大冲突避免
很难找到两端内容不同明文,使它们hash值一致(发生冲突)
哈希算法在密码学中如何应用?
登录要输入密码,如果明文保存密码,很容易被破解,那么就是用hash算法,生成一个密码的签名,后台保存这个签名。由于hash算法不可逆,黑客拿到这个签名也没有用处,在你输入密码后,后台重新计算一下hash值,与后台保存的hash值对比,相同则允许登