开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
1.哈希表
2.位图(bitmap)
3.布隆过滤器
1.哈希表
假设有这样一个数组vec={1,2,3,1,4,5,6,7,8,7,9},我们需要返回出现次数最多的一个数,我们很容易可以得出思路。
我们直接使用一个哈希表进行遍历,然后在累加数据元素出现的次数就可以了。
上面的数据量很小,所以使用哈希表并不会造成太大影响。但是,当数据量极大时,我们要怎么处理呢?2G的内存大概等于10亿字节,2.5亿的个int类型。
假设,我们有2G的内存,现在要处理20亿大小的数据,并返回出现次数top10的数据。
这时,我们使用哈希表进行统计,哈希表有键值key:数据,值value:次数。哈希表要统计一个数据就时8个字节。8*20亿=160亿即16G。现在很清楚的知道我们不可能用2G的内存一次性处理16G的数据量。
所以,这时我们就要使用哈希分流的思想,将这些数据分成10份,一份一份的处理,得到每一份数据的top10,然后再将这些数据的top10整合在一起进行求解。如此一来,我们便可以在规则内得到答案。
2.位图(bitmap)
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景,通常是用来判断某个数据存不存在的。
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景,通常是用来判断某个数据存不存在的。
假设一个集合{1,2,3,4,5},我们要统计其中2,3,4是否存在其中并将其存放起来,很容易得知我们及耗费时间又耗费空间。空间为12个字节。
这时,我们可以使用位图来确定2,3,4是否存在存放存在的记录。我们只需要建立一个数组就可以知道这些数是否存在并存放其存在的记录。
这时,我们用一个大小为2的int类型的数组去存放。
int a[2];//4个字节*2=8个字节
//拿出第2位的信息
//a[0]可以表示0-31位上面的信息,a[1]表示32-63位上面的信息。1表示存在,0表示不存在。
int numIndex=2/32;//看2这个数在哪数组的那样一个位置中。
int bitIndex=2%32;//看2这个数在元素位上的第几个。
int s=(a[numIndex]>>(bitIndex&1));//拿出第2位上的状态。
//给第2位添加状态1
a[numIndex]=a[numIndex]|(1<<bitIndex);
//给第2位添加状态0
a[numIndex]=a[numIndex]&(~(1<<bitIndex));
这样,我们便可以检测到这个数是否存在,并存放其是否存在的状态 。
3.布隆过滤器
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
布隆过滤器本质就是由多个哈希函数去确定一个内容是否存在。假设我们有k=3个哈希函数,我们要将“hi”这个数据存放在布隆过滤器当中,我们通过三个哈希函数得到一部分二进制第几位的值,我们将这个位对应的二进制变为1。然后,我们假如存“你好”到布隆过滤器当中,假如通过这三个哈希函数得到的值是一样的,我们将其存放。但是当我们要删除“hi”时,就出现问题了,因为这些地方存放了多个值,我们无法不能去删除其他的值。这就是布隆过滤器删除元素困难的原因。不过也是有解决方法的,就是增加哈希函数,但是这样复杂度更高了。应用之处有:网页URL 去重、黑名单。