给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址? 与上题条件相同,如何找到top K的IP?如何直接用Linux系统命令实现
要找到前TopK的IP地址,就是要统计每个IP地址出现多少次
分割大文件:如果能将相同IP地址放到同一个文件中
哈希分割: 从源文件中获取一个IP地址---->IP%文件份数
//构建键值对
<IP地址的整型数据,次数>
堆---->最多前K个IP地址—><次数,IP地址>
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比
特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如:
40亿的整型数据大概是16G的数据
用位图来映射的话 大概就是232-23=512M
#pragma once
#include
#include
using namespace std;
namespace LXY
{
class bitset
{
public:
bitset(size_t bitCount)
:_set(bitCount/8 + 1)
, _bitCount(bitCount)
{}
//置1操作
void set(size_t which)
{
//如果位集合给出100个比特位,那么你给100,就表示不了,范围为0~99
if(which >= _bitCount)
return;
//计算对应的字节
size_t index = (which >> 3);//除以8
size_t pos = which % 8;
//先将1移到对应的比特位上,再或上对应位上的数字
_set[index] |= (1 << pos);
}
//置0操作
void reset(size_t which)
{
if (which >= _bitCount)
return;
//计算对应的字节
size_t index = (which >> 3);//除以8
size_t pos = which % 8;
//先将1的取反0移到对应的比特位上,再与上对应位上的数字
_set[index] &= ~(1 << pos);
}
//检测which比特位是否为1
bool test(size_t which)
{
if (which >= _bitCount)
return false;
//计算对应的字节
size_t index = (which >> 3);//除以8
size_t pos = which % 8;
//与上1不等于0就代表存在
return 0 != (_set[index] & (1 << pos));
}
//返回比特位总的个数
size_t size()
{
return _bitCount;
}
//返回为1的比特位的总数
size_t count()
{
//查表
int bitCnttable[256] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
6, 7, 6, 7, 7, 8 };
size_t szcount = 0;
for (size_t i = 0; i < _set.size(); ++i)
szcount += bitCnttable[_set[i]];
return szcount;
}
public:
std::vector<unsigned char> _set;
size_t _bitCount;
};
}
void TestBitSet()
{
LXY::bitset bt(100);
bt.set(10);
bt.set(20);
bt.set(30);
bt.set(40);
bt.set(41);
cout << bt.size() << endl;
cout << bt.count() << endl;
if (bt.test(40))
cout << "40bite is 1" << endl;
else
cout << "40bite is not 1" << endl;
bt.reset(40);
cout << bt.count() << endl;
if (bt.test(40))
cout << "40bite is 1" << endl;
else
cout << "40bite is not 1" << endl;
}
int main()
{
TestBitSet();
system("pause");
return 0;
}
if(00) //出现过0次
01
else if(01) //出现过多次
10
位图+哈希函数
特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。多个比特位代表数据的状态信息
如果向布隆过滤器中插入baidu,我们用三个哈希函数将三个位置置为1
“baidu”---->1 4 7
“tecent”---->3 4 8
hash1,hash2,hash3----->三个位置
检测三个位置的状态
如果三个位置只要有一个为0,说明数据一定不存在
布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特位一定为1。所以可以按照以下方式进行查找:分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中
布隆过滤器如果告诉你数据不存在,那么一定不存在,如果告诉你存在,则有可能存在。
#pragma once
#include"biteset.hpp"
#include
#include"Common.hpp"
using namespace std;
//BloomFilter:位图+多个哈希
template<class T,class HF1 = Str2INT ,class HF2 = Str2INT2,class HF3 = Str2INT3,
class HF4 =Str2INT4,class HF5 = Str2INT5>
//哈希函数给的越多,将来产生误报的概率就也就越小
class BloomFilter
{
public:
BloomFilter(size_t size = 10)
:_bt(10 * size)
, _size(0)
{}
bool Insert(const T& data)
{
//HF1()(data)可能回越界,要%上位图的比特位数
size_t index1 = HF1()(data) % _bt.size();
size_t index2 = HF2()(data) % _bt.size();
size_t index3 = HF3()(data) % _bt.size();
size_t index4 = HF4()(data) % _bt.size();
size_t index5 = HF5()(data) % _bt.size();
_bt.set(index1);
_bt.set(index2);
_bt.set(index3);
_bt.set(index4);
_bt.set(index5);
_size++;
return true;
}
//检测是否存在,每个哈希函数都得检测
bool IsIn(const T&data)
{
size_t index = HF1()(data) % _bt.size();
if (!_bt.test(index))
return false;
index = HF2()(data) % _bt.size();
if (!_bt.test(index))
return false;
index = HF3()(data) % _bt.size();
if (!_bt.test(index))
return false;
index = HF4()(data) % _bt.size();
if (!_bt.test(index))
return false;
index = HF5()(data) % _bt.size();
if (!_bt.test(index))
return false;
//元素可能存在
return true;
}
//存储多少个元素
size_t count()const
{
return _size;
}
private:
LXY::bitset _bt;
size_t _size;
};
布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素
一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器(整型数组),插入元素时给k个计数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储空间的代价来增加删除操作。
给上千个文件,每个文件大小为1K—100M。给n个词,设计算法对每个词找到所有包含它的文件,你只有100K内存