哈希 hash
原理
Hash (哈希,或者散列)函数在计算机领域,尤为是数据快速查找领域,加密领域用的极广。
其做用是将一个大的数据集映射到一个小的数据集上面(这些小的数据集叫作哈希值,或者散列值)。
一个应用是Hash table(散列表,也叫哈希表),是根据哈希值 (Key value) 而直接进行访问的数据结构。也就是说,它经过把哈希值映射到表中一个位置来访问记录,以加快查找的速度。下面是一个典型的 hash 函数 / 表示意图:
哈希函数有如下两个特色:
•若是两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的。
•散列函数的输入和输出不是惟一对应关系的,若是两个散列值相同,两个输入值极可能是相同的。但也可能不一样,这种状况称为 “散列碰撞”(或者 “散列冲突”)。
缺点: 引用吴军博士的《数学之美》中所言,哈希表的空间效率仍是不够高。若是用哈希表存储一亿个垃圾邮件地址,每一个email地址 对应 8bytes, 而哈希表的存储效率通常只有50%,所以一个email地址须要占用16bytes. 所以一亿个email地址占用1.6GB,若是存储几十亿个email address则须要上百GB的内存。除非是超级计算机,通常的服务器是没法存储的。
因此要引入下面的 Bloom Filter。
布隆过滤器 Bloom Filter
原理
若是想判断一个元素是否是在一个集合里,通常想到的是将集合中全部元素保存起来,而后经过比较肯定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。可是随着集合中元素的增长,咱们须要的存储空间愈来愈大。同时检索速度也愈来愈慢。
Bloom Filter 是一种空间效率很高的随机数据结构,Bloom filter 能够看作是对 bit-map 的扩展, 它的原理是:
当一个元素被加入集合时,经过 K 个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。检索时,咱们只要看看这些点是否是都是 1 就(大约)知道集合中有没有它了:
•若是这些点有任何一个 0,则被检索元素必定不在;
•若是都是 1,则被检索元素极可能在。
优势
It tells us that the element either definitely is not in the set or may be in the set.
它的优势是空间效率和查询时间都远远超过通常的算法,布隆过滤器存储空间和插入 / 查询时间都是常数O(k)。另外, 散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不须要存储元素自己,在某些对保密要求很是严格的场合有优点。
缺点
可是布隆过滤器的缺点和优势同样明显。误算率是其中之一。随着存入的元素数量增长,误算率随之增长。可是若是元素数量太少,则使用散列表足矣。
(误判补救方法是:再创建一个小的白名单,存储那些可能被误判的信息。)
另外,通常状况下不能从布隆过滤器中删除元素. 咱们很容易想到把位数组变成整数数组,每插入一个元素相应的计数器加 1, 这样删除元素时将计数器减掉就能够了。然而要保证安全地删除元素并不是如此简单。首先咱们必须保证删除的元素的确在布隆过滤器里面. 这一点单凭这个过滤器是没法保证的。另外计数器回绕也会形成问题。
Example
能够快速且空间效率高的判断一个元素是否属于一个集合;用来实现数据字典,或者集合求交集。
如: Google chrome 浏览器使用bloom filter识别恶意连接(可以用较少的存储空间表示较大的数据集合,简单的想就是把每个URL均可以映射成为一个bit)
得多,而且误判率在万分之一如下。
又如: 检测垃圾邮件
假定咱们存储一亿个电子邮件地址,咱们先创建一个十六亿二进制(比特),即两亿字节的向量,而后将这十六亿个二进制所有设置为零。对于每个电子邮件地址 X,咱们用八个不一样的随机数产生器(F1,F2, ...,F8) 产生八个信息指纹(f1, f2, ..., f8)。再用一个随机数产生器 G 把这八个信息指纹映射到 1 到十六亿中的八个天然数 g1, g2, ...,g8。如今咱们把这八个位置的二进制所有设置为一。当咱们对这一亿个 email 地址都进行这样的处理后。一个针对这些 email 地址的布隆过滤器就建成了。