先看看英文的维基百科上的解释:
A hash function is any algorithm or subroutine that maps large data sets of variable length, called keys, to smaller data sets of a fixed length. For example, a person's name, having a variable length, could be hashed to a single integer. The values returned by a hash function are called hash values, hash codes, hash sums, checksums or simply hashes.
意思是说:hash散列是任何可以把大数据集映射到定长数据集的算法或子程序。
用数学公式解释:假设F是一个包含n个记录的文件空间,Ri为文件中的某个记录(1≤i≤n),keyi是其关键字值,若存在关键字值keyi与记录Ri的地址之间建立某种函数关系,则便可以通过这个函数把关键字值转换成相应记录在文件中的地址。即有:addr(Ri)=H(keyi),其中addr(Ri)为Ri的地址,H(keyi)称为哈希函数。
hash散列的应用:
1.hashtable:用来快速定位一条记录是否出现在给定集合中。
2.加密:hash算法一般是不可逆的。
3.Bloom filters:构造很大的bit数组,利用多个hash算法,判断一条记录是否已存在。用于邮件的黑名单过滤等。
4.校验:如循环冗余校验等。
5.语言识别和文件比较。
常用的著名hash算法:
HAVAL | 256/224/192/160/128 | 256 | 1024 | 64 | 32 | 是 |
MD2 | 128 | 384 | 128 | No | 8 | 大多数 |
MD4 | 128 | 128 | 512 | 64 | 32 | 是 |
MD5 | 128 | 128 | 512 | 64 | 32 | 是 |
PANAMA | 256 | 8736 | 256 | 否 | 32 | 是 |
RadioGatún | Arbitrarily long | 58 words | 3 words | 否 | 1-64 | 否 |
RIPEMD | 128 | 128 | 512 | 64 | 32 | 是 |
RIPEMD-128/256 | 128/256 | 128/256 | 512 | 64 | 32 | 否 |
RIPEMD-160/320 | 160/320 | 160/320 | 512 | 64 | 32 | 否 |
SHA-0 | 160 | 160 | 512 | 64 | 32 | 是 |
SHA-1 | 160 | 160 | 512 | 64 | 32 | 有缺陷 |
SHA-256/224 | 256/224 | 256 | 512 | 64 | 32 | 否 |
SHA-512/384 | 512/384 | 512 | 1024 | 128 | 64 | 否 |
Tiger(2)-192/160/128 | 192/160/128 | 192 | 512 | 64 | 64 | 否 |
WHIRLPOOL | 512 | 512 | 512 | 256 | 8 | 否 |
自己如何实现hash算法?
1.直接地址法:取关键字或关键字的某个线性函数值为哈希地址。即:H(key)=key或H(key)=a·key+b
2.数字分析法:假设关键字是以R为基的数(如2,8,10等),并且哈希表中可能出现的关键字都是事先知道的,则可以取关键字的若干数位来组成哈希地址。
3.平方取中法:有时一组关键字在每一位上某些数字的重复出现频率很高,例如:(0100,1100,1200,1160,2060,2163,2261,2262),这时无法是用数字分析法得到较均匀的哈希函数,平方取中法是首先求关键字的平方值,通过平方来扩大差别,然后再选其中的几位或其组合作为哈希地址。该方法适用于关键字位数少而相同的位数多的关键字。
4.折叠法(边界法)与转移法:有时关键字含位数较多,这时可将关键字值从某些地方断开,分成几段,其中一段的长度等于地址的位数,把其余折叠加到它的上面,若产生进位则舍去。
5.除留余数法:取关键字被某个不大于哈希表表长m的数p除后所得的余数作为哈希地址。即:H(key)=key MOD p (p≤m 一般取p为不大于m的最大素数。)
如何解决hash冲突?
因为是将无限大量的数据集映射到固定长度的数据集上,难免不同的key映射到同一个位置。
1.开放定址法
Hi=(H(key)+di) mod m i=1,2,……,k(k≤m-1)
其中:H(key)为哈希函数;m为哈希表表长;di为增量序列,有三种取法。
①di=1,2,……,m-1;称为线性探测再散列或线性探查法。
②di=12,-12,22,-22,32,……,±k2,(k≤m/2);称为二次探测再散列。
③di=伪随机数序列,称为伪随机探测再散列
2.再哈希法
Hi=RHi(key) i=1,2,……,k
RHi均是不同的哈希函数,即在同义词产生地址冲突时计算另一个哈希函数地址,直到冲突不再发生。这种方法不易产生聚集,但增加了计算的时间。
3.链地址法(结合的同义词子表)
把具有相同散列地址的关键字存放在同一个链表中,称为同义词表。同时用数组T存放各个链表的头指针。凡是散列地址为i的记录都以结点方式插入到以T[i]为头指针的单链表中。
4.建立一个公共的溢出区(分离的同义词子表)
假设哈希函数的值域为[0、、m-1],则设向量HashTable[0、、m-1]为基本表,每个分量存放一个记录,另设立向量OverTable[0、、v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。
参考: