位图
1.什么叫位图
位图就是使用一个比特位来进行表示数据存在与否的信息。
1个字节有8个位,那么我们每个位就可以表示,是否存在这个数据(0/1)
例如:
我们如果从0开始,那么上图就可以表示出在这些数据中,存在 1,3,8,10,21,22,23.
2.位图的使用方式:
1.首先我们需要知道需要多少个比特位(比特位的个数=max-min+1)
2.将数据映射到位图当中去。
3.进行查找,时间复杂度为O(1).
位图的简单实现,
在C++中提供了位图的使用方法,在bitset中有使用方法,下面我自己简单的实现了一下。
在位图中,我们要有插入,删除,和查询功能。
在进行这三步的时候,首先我们需要计算出这个数据映射的是哪个字节,哪个比特位。
对于插入,删除,和查询,我们就进行相关的位操作就可以了。
namespace bite
{
template<size_t N> //N表示比特位的总数
class biteset
{
public:
biteset()
:_bs(N / 8 + 1), _count(0)
{}
void set(size_t pos)
{
assert(pos < N);
size_t Byte = pos / 8;
size_t Bit = pos % 8;
_bs[Byte] |= (1 << Bit);
++_count;
}
void reset(size_t pos)
{
assert(pos < N);
size_t Byte = pos / 8;
size_t Bit = pos % 8;
_bs[Byte] &= ~(1 << Bit);
--_count;
}
bool test(size_t pos)
{
assert(pos < N);
size_t Byte = pos / 8;
size_t Bit = pos % 8;
return 0 != (_bs[Byte] & (1 << Bit));
}
size_t count() const
{
return _count;
}
size_t size()const
{
return N;
}
private:
std::vector<char>_bs;
size_t _count; //1的个数
};
}
3.位图的应用场景。
1.快速查询某一个无符号整形是不是在一个集合中?
我们只需要将数据映射到位图中,就可以查询。
我们要注意的时,比如给我们40亿的数据,我们在使用位图的时候,大小并不是按照40亿来说,而是按照整形的取值范围来计算。变形:对于一个集合,查询只出现一次的数据?
这时候,我们如果要使用位图的话,每一种数据就有三种结果 不存在,存在一次,存在多次。我们就需要使用两个位来进行表示。00 表示不存在,01表示存在一次,10 表示存在多次。重复上面的操作,就可以找到。
变形:对于一个集合,查询出现不少于一次的数据。
这个方法和上面一样。
2.可以进行排序。
首先我们将数据映射到位图当中去,然后在进行回收。回收的时候,我们从数据的最小值开始,依次去判断,是否存在,就可以进行排序。
但是如果出现了重复的元素,就不能显示出来。
3.求集合的交集和并集
我们可以将两个集合映射到两个位图当中去,然后一次去比较就可以求出来了。
4.位图的缺陷
1.不能处理重复的数据。
2.一般情况下只能处理整形。