什么是海量数据处理
所谓海量数据处理,无非就是基于海量数据上的存储、处理、操作。何谓海量,就是数据量太大,所以导致要么是无法在较短时间内迅速解决,要么是数据太大,导致无法一次性装入内存。
那解决办法呢?针对时间,我们可以采用巧妙的算法搭配合适的数据结构,如Bloom filter/Hash/bit-map/堆/数据库或倒排索引/trie树,针对空间,无非就一个办法:大而化小,分而治之(hash映射),你不是说规模太大嘛,那简单啊,就把规模大化为规模小的,各个击破不就完了嘛。下面我们来讲讲使用堆、快排分割、map、set、bitmap解决topk问题和查重问题。
查重问题
查重就是在一组海量数据中查找重复的数字,我们一听到查重,就会想到哈希,如果对内存有比较大的要求时,我们好可以使用bitmap,但是,bitmap开辟的数组大小会影响其性能,我们要解决内存和性能问题的话,可以使用Bloom Filter布隆过滤器,至于使用哪种方法,就得看具体的使用场景,没有最好的方法,只有最合适的方法。
1、哈希表
C++STL库中的无序关联容器的底层就是Hash表
哈希表的查找效率接近于o(1),查找的效率很高
2、bitmap
bitmap是通过开辟辅助数组的每一比特位来标识每个数据的状态,例如:0表示未出现过,1表示出现过,通过找出数据中的最大值max,来计算算开辟数组的大小,如果,数组的每个元素类型为插入型,我们就可以使用公式:size = max/8 + 1来计算出辅助数组的大小。从而用每一个位来标识数据的状态(已存在或者未存在),位图法也是有缺点的:比如说:有十个整数,最大的值为1亿,我们就要开辟1亿大小的辅助数组,这样就会浪费多余的空间。
查重问题应用举例
在10亿个整形数字(0<val<100000000)中找到第一个重复的数字?
方案一:哈希表
当我们使用哈希表来解决查重问题的时候就得注意对内存的大小有没有要求,10亿个数字也就是大概1G个数字所占内存是4个G,由于哈希表是通过开链法来解决哈希冲突的,所以每个数据都会有对应的指针域,所以当我们将数据一次性加载所需要的内存大小大概为8G,如果没有对内存大小做限制的话,可直接使用set来统计重复的数字。(map还可以用来统计对应数字重复的次数)
使用set查询重复的数字(这里为了提升速率,将数字范围缩小到20000)
#include <iostream>
#include <unordered_set>
#include <unordered_map>
using namespace std;
int main()
{
vector<int> vec;
vector<int> vec1;
for (int i = 0; i < 20000; i++)//给出20000个随机数
{
vec.push_back(rand());
}
cout << endl;
unordered_set<int> myset;//定义set(哈希表)
for (int val : vec)//对随机数组进行遍历
{
if (myset.find(val) != myset.end())//如果set中没找到,说明数字重