情景1:对无反复的数据进行排序
@给定数据(2,4。1,12。9,7,6)怎样对它排序?
方法1:主要的排序方法包含冒泡,快排等。
方法2:使用BitMap算法
方法1就不介绍了。方法2中所谓的BitMap是一个位数组。跟平时使用的数组的唯一区别在于操作的是位。
首先是开辟2个字节大小的位数组。长度为16(该长度由上述数据中最大的数字12决定的)如图
然后。读取数据,2存放在位数组中下标为1的地方,值从0改为1。4存放在下标为3的地方,值从0改为1....结果如图
最后,读取该位数组,得到排好序的数据是:(1,2。4,6。7。9。12)
比較方法1和方法2的区别:方法2中,排序须要的时间复杂度和空间复杂度非常依赖与数据中最大的数字比方12,因此空间上讲须要开2个字节大小的内存,时间上须要遍历完整个数组。
当数据类似(1,1000。10万)仅仅有3个数据的时候。显然用方法2,时间复杂度和空间复杂度相当大,可是当数据比較密集时该方法就会显示出来优势。
情景2:对有反复的数据进行判重
数据(2,4,1,12,2。9,7,6。1。4)怎样找出反复出现的数字?
首先是开辟2个字节大小的位数组。长度为16(该长度由上述数据中最大的数字12决定的)如图
当读取完12后。数组中的数据例如以下图:
当读取2的时候,发现数组中的值是1。则推断出2是反复出现的。
应用
应用1:某文件里包括一些8位的电话号码,统计出现的号码的个数?(推断有谁出现)
8为最大是99 999 999。大约是99M的bit,12.5MB的内存,就能够统计出来出现的号码。
应用2:某文件里包括一些8位的电话号码。统计仅仅出现一次的号码?(推断有谁出现而且指出现1次)
须要扩展一下,能够用两个bit表示一个号码,0代表没有出现过。1代表仅仅出现过1次,2代表至少出现2次。
应用3:有两个文件,文件1中有1亿个10位的qq号码,文件2中有5千万个10位qq号码,推断两个文件里反复出现的qq号。
首先建立10的10次方个大小的位数组(占用内存大约是1.25G)。所有初始化为0。读取第一个文件,相应的qq号存放到相应的未知,数值改为1。假设反复出现仍是1.读取完成第一个文件后。读取第二个文件。相应的位置为1则表示反复出现。
应用4:有两个文件,文件1中有1亿个15位的qq号码,文件2中有5千万个15位的qq号码,推断两个文件里反复出现的qq号。
应用4中,qq号码上升为15位的时候。显然内存是不够用了,这个时候怎么办?使用Bloom Filter(布隆过滤器)
Bloom Filter(布隆过滤器):
对于Bit-Map分析一下,每次都会开辟一块表示最大数值大小的bit数组,比方情景1中的16,将相应的数据经过映射到bit数组的下标,这事实上是一种最简单的hash算法,对1去模。在上述应用4中,当qq号码改为15位的时候。Bit-Map就不太好用了,怎样改进呢?解决的方法:降低bit数组的长度,可是添加hash函数的个数
对于每个qq号码,我用K个hash函数,经过k次映射,得到k个不同位置,如果k=3,那么对于一个qq号码,映射到位数组中3个不同的位置
当读取第二个包括5千万个qq号码的文件的时候,使用相同的3个hash函数进行映射,当3个位置所有是1的时候才表示出现过,否则表示没有出现过。
有什么疑问吗?
显然,对于一个qq号码,假设它在第一个文件里没有出现过。可是它映射的3个位置已经所有是1的情况会有吗?答案是会的,可是这样的概率是可控的,可控的意思是:这样的误差跟hash函数的个数和质量是有关系的。能够通过控制hash函数的个数和位数组的大小来控制误差概率。至于表示3者之间的关系精确的数学公式就不再具体研究了。
能够这样讲。布隆过滤器是Bit-Map的进一步扩展,对于大数据量判重。布隆过滤器能够在内存中进行推断,避免了对磁盘的读写,效率是非常高的。以上是自己关于两者的理解,有错误望不吝赐教。