【一】位图的概念
位图,就是用每一个比特位来存放某种状态,适用于海量数据,整数,数据无重复的场景,通常是用来判断某个数据存不存在的。例如:10个整数本应该存放四十个字节,此时用位图只需要十个比特位,也就是三个字节。
【二】位图的实现
class MyBitmap
{
public:
MyBitmap()
{
//默认为两个字节,且为16个比特位
this->elem = new char[1];
}
MyBitmap(int n)
{
this->elem = new char[n / 16 + 1];
}
void set(int val)//存放这个值
{
if (val < 0) {
assert("输入的值有误,请重新检查!");
}
int ArrayIndex = val / 16;
int BitIndex = val % 16;
this->elem[ArrayIndex] |= (1 << BitIndex);
usedSize++;
}
bool get(int val)//寻找这个值是否是真的在这个位图上面
{
if (val < 0)
{
assert("输入的值有误,请重新检查!");
}
int ArrayIndex = val / 16;
int BitIndex = val % 16;
if (this->elem[ArrayIndex] & (1 << BitIndex) != 0)
{
return true;
}
return false;
}
void CancelSet(int val)
{
if (val < 0)
{
assert("输入的值有误,请重新检查!");
}
int ArrayIndex = val / 16;
int BitIndex = val % 16;
this->elem[ArrayIndex] &= ~(1 << BitIndex);
usedSize--;
}
private:
char* elem;
public:
int usedSize;
};
【三】位图的缺陷应用
应用:
1.快速查找某一个数据是否在一个集合中
2.排序+去重
3.求两个集合的交集,并集
4.操作系统中磁盘块标记
缺陷:
1.只能存放整数,对字符串类型是没有办法进行存储的
2.只能知道一个数据是否存在,并不能知道这个数据是存在几次
【四】布隆过滤器
1.布隆过滤器的提出
一般来说,计算机中的集合是用哈希表来存储的是,它的好处是快速准确,缺点是废内存,当集合较小时,这个问题不是十分明显,但是如果集合是很巨大的时,哈希表存储效率是非常低下的。如:Yahoo,Hotmaill这种公众电子邮件提供商,需要去过滤那些发送垃圾邮件的人的垃圾邮件,其中一个办法就是记下这些垃圾邮件的地址,但是因为邮件地址是可以随意注册的,所有目前来说最少有几十亿个发垃圾邮件的地址,将他们存起来则需要大量的网络服务器。如果使用哈希表来存储,则需要200g左右的内存,而一般的电脑上是很难达到这样的内存规格的。
1.用哈希表存储用户地址,缺点:浪费空间
2.用位图存储用户地址,缺点:如果那个地址是字符串,这是非常无能为力的
3.所以将哈希表和位图相结合,就是布隆过滤器
【五】布隆过滤器概念
布隆过滤器由布隆在布隆在1970年提出的一种紧凑型,比较巧妙的概率型数据结构,特点是高效的插入和查询,可以用来告诉你某样东西一定不存在或者可能存在,它由多个哈希函数,将一个数据映射到位图结构中,此种方式不仅可以提升查询效率吗,也可以节省大量的空间。
【六】布隆过滤器的插入
向布隆过滤器中插入:“baidu”,“tenxun”
【七】布隆过滤器的查找
布隆过滤器思想是将一个元素用多个哈希函数映射多个哈希函数映射到每一个位图中,因此映射到的位置比特位一定为一,所以可以按照以下方式进行查找;分别计算每个哈希值对应的值是否为0,只有一个为零,就代表该元素一定不在哈希表中,否则可能在哈希表中。
比如:在布隆过滤器中查找“alibaba”时,假设3个哈希计算的哈希值为1,3,7,刚好和其他元素的比特位重叠,此时布隆过滤器告诉该元素存在,但是该元素是不存在的。