一、位图概念
今天学校的课还挺多的,不过我也没怎么听,嘤嘤嘤,好不容易的抽出一点时间整理下位图。进入正题吧
位图(bitset)是一种常见的数据结构,常用在给一个很大范围的数(比如我之前看到一个题是有四十亿个数),判断其中的数是不是在其中。这里就要用到位图,显然这么多得数在内存中是存不下的,我们就得重新想办法。位图在索引、数据压缩有很大的应用。
位图使用数组实现的,数组的每一个元素的每一个二进制位都表示一个数据,0表示该数不存在,1表示该数据存在。
二、位图模型
回到我们之前说的问题,有四十亿个数,内存怎么存?位图想到一个办法,一个int型的数字是4个字节,32个比特位,如果我们把每一个比特位标志一个数字,那一个字节就可以标记32个数字(注意:位图不存放这些数据,只是标记是否存在,位图中的数组存放的是二进制数字0或者1)
40亿个数字大概就是16g,而现在使用位图16g/32大约就是500M左右,内存省掉很多很多,效率也同时提高了
三、位图的设计
如果上的内容你明白了,那设计位图你也应该没啥问题,我们采用vector数组作为底层,这样可以开辟一段连续的空间,而range>>5(range表示的是要统计的数字规模)就相当于除以32,后面+1,是为了防止小于32 的数除以32商为0。
class bitmap
{
public:
bitmap(size_t range) //range表示数的集合大小
{
_bit_table.resize((range >> 5) + 1); //这里表示40亿个数要开多大的空间存储
}
private:
vector<int> _bit_table;
};
位图元素的设置
解释都在代码的注释
void setbit(size_t x)
{
size_t index = x >> 5; //算出x在第几个整型位
size_t n = x % 32; //在某个整型位的具体位置
_bit_table[index] |= (1 << n); //将该具体位置为1,其他位不变
}
移除该数字
为了移除该数字,我们只需要把该位置为0,其他位不变
void removebit(size_t x)
{
size_t index = x >> 5;//算出x在第几个整型位
size_t n = x % 32; //在某个整型位的具体位置
_bit_table[index] &=~(1 << n); //将该位置为0,其余位置为1
}
位图元素的查找
int find(size_t x)
{
size_t index = x >> 5;//算出x在第几个整型位
size_t n = x % 32; //在某个整型位的具体位置
return _bit_table[index] & (1 << n); //返回0或者1
}