1. 给定一个大小超过 100G 的文件, 其中存在 IP 地址, 找到其中出现次数最多的 IP 地址(hash文件切分)
我们先定义一个位图,这里用uint64_t举例(64位为一个单位来表示)
代码实现如下:
#include "bitmap.h"
#include <stdio.h>
void Is_Only_One(BitMap* bm1,BitMap* bm2,size_t arr[],int size)
{
if(bm1 == NULL || bm2 == NULL || arr == NULL || size < 1)
{
return;
}
int i = 0;
for(; i < size; ++i)
{//这里规定只有是
// 00 -> 不存在
// 01 -> 存在一次
// 10 -> 存在,并且多于一次
if(BitMapTest(bm1,arr[i]))
{//如果是 1x 就证明已经存在多于一次了,就不用再判断这个数字了,继续判断下一个数字即可
continue;
}
else if(BitMapTest(bm1,arr[i]) == 0 && BitMapTest(bm2,arr[i]) == 0)
{//这里证明是 00,即还没有出现,这里让他变为 01
BitMapSet(bm2,arr[i]);
}
else if(BitMapTest(bm1,arr[i]) == 0 && BitMapTest(bm2,arr[i]) == 1)
{//这里证明是 01,即只出现了一次,这里让他变为 10
BitMapSet(bm1,arr[i]);
BitMapUnset(bm2,arr[i]);
}
}
//退出循环以后证明数组里面所有的元素都已经访问完了
for(i = 0; i < size; ++i)
{
if(BitMapTest(bm1,arr[i]) == 0 && BitMapTest(bm2,arr[i]) == 1)
{
printf("%lu\n",arr[i]);
}
}
}
void Test()
{
size_t arr[] = {1,1,1,2,2,3};
BitMap bm1;
BitMap bm2;
BitMapInit(&bm1,65);
BitMapInit(&bm2,65);
int size = sizeof(arr)/sizeof(arr[0]);
Is_Only_One(&bm1,&bm2,arr,size);
}
int main()
{
Test();
return 0;
}
3. 有两个文件, 分别有100亿个query(查询词, 字符串), 只有1G内存, 找到两个文件的交集(hash文件切分 + 布隆过滤器).
利用布隆过滤器(位图)的思想,查找字符串是否存在,因为文件太大,内存装不下,所以还要进行文件切分
哈希切分:
对文件A进行哈希切分,读取每一盒query值,计算hash值,例如我们要切分成100份,就让哈希值模上100,如果模得值为0,就把这个query放到布隆过滤器中,这个时候我们就得到了 0 号集合;遍历文件 B,对其中的query计算hash值,模上100,如果模为 0,就在布隆过滤器中查找
依次处理 1 号集合(hash值模100 == 1),2 号集合,3 号集合...
4.哈希切分的一个应用场景(服务器集群)
5. 给上千个文件, 每个文件大小为1K - 100M, 设计算法找到某个词存在在哪些文件中(倒排索引).
不靠谱的方法a)遍历所有文件,如果存在就返回文件 -> 代价太高,速度慢
倒排索引,在线下完成,查找的时候直接输出对应文件,速度快,效率高