定义:位图(bitmap)就是利用每一位来存储某种状态,但是状态又比较少的情况。
缺点:
1,只能用于整形;
2,可读性差;
3,位图存储的元素个数虽然比一般做法多,但是存储的元素大小受限于存储空间的大小。位图存储性质:存储的元素个数等于元素的最大值。比如, 1K 字节内存,能存储 8K 个值大小上限为 8K 的元素。(元素值上限为 8K ,这个局限性很大!)比如,要存储值为 65535 的数,就必须要 65535/8=8K 字节的内存。要就导致了位图法根本不适合存 unsigned int 类型的数(大约需要 2^32/8=5 亿字节的内存)。
4,位图对有符号类型数据的存储,需要 2 位来表示一个有符号元素。这会让位图能存储的元素个数,元素值大小上限减半。 比如 8K 字节内存空间存储 short 类型数据只能存 8K*4=32K 个,元素值大小范围为 -32K~32K
应用:
1,给定100亿个整数,找出其中只出现过一次的整数; (1G:10亿字节,所以存放需要320G)
思路:将100一个数拆成1000份,再将每份使用位图,使用两位bit表示数字出现的次数(00:没出现过的数,01:出现一次的数,10:出现多次的数),再讲次数为1的合并到一个文件即可。
2,给两个分别有100亿个整数的文件,但是内存只有1G,找出两文件的并集;
思路:1,暴力求解O(N);2,排序+遍历O(NlgN);3,布隆过滤器(哈希+位图);4,哈希切分
3,一个没有排过序,有40亿个不相同的无符号整数,如何在其中快速判断是否有一个给定的值;
4,使用位图法进行整型数组排序。
思路:遍历数组找到max,min。根据这两个值缩小位图范围,注意对于int的负数转换为无符号整数,且取位时数字减去最小值。
实现:
class BitMap
{
public:
BitMap()
{}
BitMap(size_t size)
{
_table.resize((size >> 5) + 1);
}
void Set(int data) //置1
{
size_t ByteNo = data >> 5; //数组中的那个元素
size_t BitNo = data % 32; //32位bit位的那个bit位
_table[ByteNo] |= (1 << BitNo); //置1
}
void ReSet(int data) //置0
{
size_t ByteNo = data >> 5;
size_t BitNo = data%32;
_table[ByteNo] &= ~(1 << BitNo);
}
bool IsIn(int data)
{
size_t ByteNo = data >>5;
size_t BitNo = data%32;
if(_table[ByteNo]&(1 << BitNo))
return true;
return false;
}
private:
vector<int> _table;
}