散列的概念属于查找,它不以关键字的比较为基本操作,采用直接寻址技术。在理想情况下,查找的期望时间为O(1)。
hash函数就是把任意长的输入字符串变化成固定长的输出字符串的一种函数。输出字符串的长度称为hash函数的位数。
散列(Hashing)通过散列函数将要检索的项与索引(散列,散列值)关联起来,生成一种便于搜索的数据结构(散列表)。
目前应用最为广泛的hash函数是SHA-1和MD5,大多是128位和更长。hash函数在现实生活中应用十分广泛。很多下载网站都提供下载文件的MD5码校验,可以用来判别文件是否完整,在一些BitTorrent下载中,软件将通过计算MD5检验下载到的文件片段的完整性,etc。
哈希冲突是不可避免的,因为键的数目总是比索引的数目多,不管是多么高明的算法都不可能解决这个问题。就算键的数目比索引的数目少,必有一个输出串对应多个输入串,冲突还是会发生。
hash函数的构造准则:简单、均匀。
(1)散列函数的计算简单,快速;
(2)散列函数能将关键字集合K均匀地分布在地址集{0,1,…,m-1}上,使冲突最小。
取关键字或关键字的某个线性函数值为哈希地址:H(key) = key 或 H(key) = a·key + b 其中a和b为常数,这种哈希函数叫做自身函数。
注意:由于直接定址所得地址集合和关键字集合的大小相同。因此,对于不同的关键字不会发生冲突。但实际中能使用这种哈希函数的情况很少。
首先用关键字key乘上某个常数A(0 < A < 1),并抽取出key.A的小数部分;然后用m乘以该小数后取整。
注意:该方法最大的优点是m的选取比除余法要求更低。比如,完全可选择它是2的整数次幂。虽然该方法对任何A的值都适用,但对某些值效果会更好。Knuth建议选取 0.61803……。
取关键字平方后的中间几位为哈希地址。
通过平方扩大差别,另外中间几位与乘数的每一位相关,由此产生的散列地址较为均匀。这是一种较常用的构造哈希函数的方法。
将一组关键字(0100,0110,1010,1001,0111) 平方后得(0010000,0012100,1020100,1002001,0012321) 若取表长为1000,则可取中间的三位数作为散列地址集:(100,121,201,020,123)。
取关键字被数p除后所得余数为哈希地址:H(key) = key MOD p (p ≤ m)。
注意:这是一种最简单,也最常用的构造哈希函数的方法。它不仅可以对关键字直接取模(MOD),也可在折迭、平方取中等运算之后取模。值得注意的是,在使用除留余数法时,对p的选择很重要。一般情况下可以选p为质数或不包含小于20的质因素的合数。
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即 H(key) = random (key),其中random为随机函数。通常,当关键字长度不等时采用此法构造哈希函数较恰当。