提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
不同于树的存储结构,哈希表是一种基于键值对的存储表,不需要由根节点向下比较,而是直接找到查询值得位置,查询可达O(1)
一、哈希表是什么?
哈希表是一种基于哈希函数的存储表,查询可达O(1).
相较于数组和链表,哈希表有什么优势?
数组是一种连续的地址结构,特点是便于查询,不利于插入和删除;
链表是一种不连续的地址结构,特点是便于插入和删除,不利于查询。
哈希表则是查询也快,又便于查找和删除,结合了数组和链表的使用。
二、什么是哈希函数?
通过某种算法将key值转换成index的值,这样在查找key的时候可以直接通过哈希算法找到对应位置,而不像数组或树需要比较,查询可达O1。
方法简述:
1.除留余数法(常用)
H(key)=key MOD p (p<=m m为表长)
该方法重点在于p的选择,根据前人经验,p应为不大于表长的质数或是不含20以下的质因子的合数,这样可以减少地址的重复(冲突)
例子:比如key为7,10,13,15,22,表长为6,则p取5.
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
key | 10 | 7 | 13 | 22(冲突后移) |
2.折叠法
如果数字的位数很多,可以将数字分割为几个部分,取他们的叠加和作为hash地址
使用
比如key=123 456 789
我们可以存储在61524,取末三位,存在524的位置
该方法适用于数字位数较多且事先不知道数据分布的情况
3.平方取中法
如果关键字的每一位都有某些数字重复出现频率很高的现象,可以先求关键字的平方值,通过平方扩大差异,而后取中间数位作为最终存储地址。
比如key=1234 1234^2=1522756 取227作hash地址
比如key=4321 4321^2=18671041 取671作hash地址
这种方法适合事先不知道数据并且数据长度较小的情况
4.数字分析法
假设关键字集合中的每个关键字key都是由s位数字组成,分析key中的全体数据,并从中提取分布均匀的若干位或他们的组合构成全体。
我们知道身份证号是有规律的,现在我们要存储一个班级学生的身份证号码,假设这个班级的学生都出生在同一个地区,同一年,那么他们的身份证的前面数位都是相同的,那么我们可以截取后面不同的几位存储,假设有5位不同,那么就用这五位代表地址。
H(key)=key%100000
此种方法通常用于数字位数较长的情况,必须数字存在一定规律,其必须知道数字的分布情况,比如上面的例子,我们事先知道这个班级的学生出生在同一年,同一个地区。
5.直接定址法
哈希函数为关键字的线性函数如 H(key)=a*key+b
这种构造方法比较简便,均匀,但是有很大限制,仅限于地址大小=关键字集合的情况。
三.哈希冲突
1.什么是哈希冲突?
不同的key值通过函数计算得出的index相同
2.如何解决
开放定制法:
函数:Hi=(H(key)+di)MODm
di的取值方法:
1.线性探测再散列
di=c*i
举例:
缺点:某些点冲突太多,后移很多次,导致查询时要多次比较,效率降低
2.平方探测再散列
di=1^2,-1^2,2^2,-2^2,3^2.......
研究表明:当表的长度为质数且表装载因子a不超过0.5时,新的表项一定能够插入,而且任何一个位置都不会被探查两次。因此只要表中有一半的空位置,就不会存在表满的问题。在搜索时可以不考虑表装满的情况,但在插入时必须确保表的装载因子a不超过0.5,如果超出必须考虑增容。
因此:平方散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷。
3.随机探测在散列
一组随机数列
链地址法:(常用)
这样就结合了数组以及链表的使用,通过哈希算法将key转成index值,如果冲突则在数组后接上链表,储存冲突的key的value,链表采用头插法,因为新插入的值大概率会再次使用,这样方便查找
rehash:
当冲突过多,就会造成链很长,慢慢的效率也就降低了,这时需要我们对哈希表进行扩容了,一般扩大到原来的二倍,并重新选择p的值。
扩容的时机:
对于哈希表的存储能力,设定了装载因子:所有元素个数/数组长度,一般将这个值设置为0.75作为临界值,超过则进行扩容。
四.哈希表的查找效率
决定hash表查找的ASL因素:
1)选用的hash函数
2)选用的处理冲突的方法
3)hash表的饱和度,装载因子 α=n/m(n表示实际装载数据长度 m为表长)
一般情况,假设hash函数是均匀的,则在讨论ASL时可以不考虑它的因素hash表的ASL是处理冲突方法和装载因子的函数
五.链地址法和开放定址法比较
开放地址法需要保持大量的空间以位置查找效率,而链地址法虽然需要储存链接指针,但更省空间,并且链地址法更利于插入和删除。
六.删除数据
对于链地址法可以直接删除数据,而开放定址法不可以,应删除后在原有位置填入不存在的数据。
总结
哈希表重点在于哈希函数的选择以及如何解决哈希冲突问题,这是影响其查找效率的主要因素,哈希函数常用除留余数法,解决哈希冲突常用链地址法。