目录
(2)给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件的交集
(3)一个文件有100亿个整数,1G内存,设计算法找到出现次数不超过2次的所有整数。
(1)给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件的交集?给出近似算法。
(1)给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件的交集?给出精确算法。
(2)给一个超过100G大小的log file,log中存着IP地址,设计算法找到出现次数最多的IP地址?如何找到top K的IP?如何直接用Linux系统命令实现?
海量数据处理是指基于海量数据的存储和处理,正因为数据量太大,所以导致要么无法在短时间内迅速处理,要么无法一次性装入内存。
①我们标记整数时可以将其分为三种状态:
②解释
③代码示例
- #include
- #include
- #include
- #include
- using namespace std;
-
- int main()
- {
- //此处应该从文件中读取100亿个整数
- vector<int> v{ 9, 34, 8, 72, 3, 45, 9, 8, 27, 3, 2, 3, 45, 8, 45};
-
- //在堆上申请空间
- bitset<4294967295>* bs1 = new bitset<4294967295>;
- bitset<4294967295>* bs2 = new bitset<4294967295>;
- //bitset<-1> bs;
-
- //处理数据
- for (auto e : v)
- {
- if (!bs1->test(e) && !bs2->test(e)) //00->01
- {
- bs2->set(e);
- }
- else if (!bs1->test(e) && bs2->test(e)) //01->10
- {
- bs1->set(e);
- bs2->reset(e);
- }
- else if (bs1->test(e) && !bs2->test(e)) //10->10
- {
- //不做处理
- }
- else //11(理论上不会出现该情况,保证代码的完整性)
- {
- assert(false);
- }
- }
-
- for (size_t i = 0; i < 4294967295; i++)
- {
- if (!bs1->test(i) && bs2->test(i)) //01
- cout << i << endl;
- }
-
- return 0;
- }
④补充
①方法1:(一个位图需要512M内存)
②方法2: (两个位图刚好需要1G内存,满足要求)
③对于32位的整型,无论待处理的整数个数是多少,开辟的位图都必须有 2^32 个比特位,也就是512M,因为我们要保证每一个整数都能够映射到位图当中,因此这里位图的空间消耗是固定的。
①该题目和(1)中的方法是一样的,在该题目中我们标记整数时可以将其分为四种状态:
②一个整数要表示四种状态也是只需要两个位就够了,此时当我们读取到重复的整数时,就可以让其对应的两个位按照00→01→10→11的顺序进行变化,最后状态是01或10的整数就是出现次数不超过2次的整数
③代码
- #include
- #include
- #include
- using namespace std;
-
- int main()
- {
- vector<int> v{ 9, 34, 8, 72, 3, 45, 9, 8, 27, 3, 2, 3, 45, 8, 45};
-
- //在堆上申请空间
- bitset<4294967295>* bs1 = new bitset<4294967295>;
- bitset<4294967295>* bs2 = new bitset<4294967295>;
-
- for (auto e : v)
- {
- if (!bs1->test(e) && !bs2->test(e)) //00->01
- {
- bs2->set(e);
- }
- else if (!bs1->test(e) && bs2->test(e)) //01->10
- {
- bs1->set(e);
- bs2->reset(e);
- }
- else if (bs1->test(e) && !bs2->test(e)) //10->11
- {
- bs2->set(e);
- }
- else //11->11
- {
- //不做处理
- }
- }
-
- for (size_t i = 0; i < 4294967295; i++)
- {
- if ((!bs1->test(i) && bs2->test(i)) || (bs1->test(i) && !bs2->test(i))) //01或10
- cout << i << endl;
- }
-
- return 0;
- }
题目要求给出近似算法,也就是允许存在一些误判,可以用布隆过滤器:
①布隆过滤器一般不支持删除操作
②如果要让布隆过滤器支持删除,就必须要做到以下两点:
①基本思路
②在切分时需要选择一个哈希函数进行哈希切分

③只需要分别找出A0与B0的交集、A1与B1的交集、…、A399与B399的交集,最终将这些交集和起来就是A文件和B文件的交集。

④各个小文件之间又应该如何找交集
⑤本质这里在进行哈希切分时,就是将这些小文件看作一个个的哈希桶,将大文件中的query通过哈希函数映射到这些哈希桶中,如果是相同的query,则会产生哈希冲突进入到同一个小文件中。

①找到次数最多
②找到top K的IP
③Linux系统命令实现




