位图>
一.什仫是位图>
顾名思义位图就是用每一位来保存数的状态的结构.位图是bitMap的缩写,适用于大规模数据但是数据状态又不是很多的情况的,因为一个位只有0和1两种状态,所以位图就是只用每一位来保存数的状态的结构.
二.一道海量数据查找的题>
在了解了位图的概念之后我们发现位图通常用于大规模的数据而且用于判断某一个数是否在这个范围之内,在这里就引出了这样一道海量数据查找的题目:
40亿个不重复的无符号的整数,没排过序。给定一个无符号的整数如何快速的判断一个数是否在这40亿个数中???
对于这道题我们该如何处理呢?
对于无符号的整形,我们知道一个整形(int)是4个字节32个位,要存储这40亿个数我们大概需要40亿*4个字节,换算下来就是16G ,也就是说我们需要16G个内存来存储这40亿个数这显然是不太现实的而且查找的效率也并不是很高。
这就用到了之前提到的位图来解决了,如果我们只用一个位来代表该数据存在还是不存在,0代表不存在,1代表存在,那仫此时的4个字节可以代表的不再是1个整数而是32个整数,此时我们只需要500M的内存就可以处理这个问题了.
三.位图的应用>
位图一般用于海量数据的查找,但是位图却存在一个缺点就是只能解决正整数的查找问题.
1.给定100亿个整数,如何找到只出现一次的整数?
答:对于整形(int)而言只能表示的数据最大为42亿多,对于100亿个整形值来说必然是存在重复的而且有的数据可能不止一次的重复出现,如果用继续用一位来表示该数据存在还是不存在肯定是不可以的:0表示不存在,1表示存在,一个数出现一次就将对应的位置1那仫再出现呢?置0吗???此时的这个0代表的是不存在还是出现了两次呢?用两个位呢?(00:不存在,01:出现一次,10:出现多次,11:舍弃),也就是2bitMap, 最后出现只有1次的数即为所求.
2.1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数?
答:实现思路类似题目1,但是此时内存只有1G那就用到了哈希切分,将这个大文件切分成若干个小文件,再用2bitMap来解决.
四.位图的实现>
#pragma once
#include<vector>
class BitMap
{
public:
BitMap(size_t range)
{
_bitMap.resize((range >> 5) +1);
}
void Set(size_t x)
{
size_t index=x>>5;
size_t num=x%32;
_bitMap[index] |= (1 << num);
}
void ReSet(size_t x)
{
size_t index=x>>5;
size_t num=x%32;
_bitMap[index] &= (~(1 << num));
}
bool Test(size_t x)
{
size_t index=x>>5;
size_t num=x%32;
return _bitMap[index] & (1 << num);
}
protected:
vector<size_t> _bitMap;
};
void TextBitMap()
{
BitMap bm(1024);
bm.Set(4);
bm.Set(44);
bm.Set(444);
cout<<"Test 4?"<<bm.Test(4)<<endl;
cout<<"Test 44?"<<bm.Test(44)<<endl;
cout<<"Test 444?"<<bm.Test(444)<<endl;
bm.ReSet(44);
cout<<"Test 44?"<<bm.Test(44)<<endl;
}