Bitmap 算法

事实上,针对时间问题,可以采用巧妙的算法搭配合适的数据结构(如布隆过滤器、哈希、位图、堆、数据库、倒排索引、Trie树)来解决;而对于空间问题,可以采取分而治之(哈希映射)的方法,也就是说,把规模大的数据转化为规模小的,从而各个击破。


今天我们来聊聊 Bitmap 算法。


Bitmap 算法

中文叫做位图算法


这里所说的位图不是像素图片,而是内存中连续的二进制位(bit),用于对大量整型数据做去重和查询。


举个例子,给定一块长度是 10bit 的内存空间,想要依次插入整型数据 4,2,1,3。 给定长度是10的bitmap,每一个bit位分别对应着从0到9的10个整型数。此时bitmap的所有位都是0。

1. 把整型数4存入bitmap,对应存储的位置就是下标为4的位置,将此bit置为1。

2. 把整型数2存入bitmap,对应存储的位置就是下标为2的位置,将此bit置为1。

3. 把整型数1存入bitmap,对应存储的位置就是下标为1的位置,将此bit置为1。

4. 把整型数3存入bitmap,对应存储的位置就是下标为3的位置,将此bit置为1。


要问此时bitmap里存储了哪些元素?显然是4,3,2,1,一目了然。


Bitmap不仅方便查询,还可以去除掉重复的整型数。


——————————————————————————————————(微信公众号)

为什么要让一个用户对应多个标签,而不是一个标签对应多个用户呢?

我可以先建立一个用户名和用户 ID 的隐射,然后让每一个标签包含此标签的所有用户的 ID,就像倒排索引一样!


1. 建立用户名和用户ID的映射:

2. 让每一个标签存储包含此标签的所有用户ID,每一个标签都是一个独立的Bitmap。

3. 这样,实现用户的去重和查询统计,就变得一目了然:

————————————————————————————————————(微信公众号)


HashSet 和 HashMap 也同样能实现用户的去重和统计,为什么要使用 Bitmap 呢?

如果 HashSet 和 HashMap 存储的话,每一个用户 ID 都要存成 int,占 4 字节即 32bit。而一个用户在 Bitmap 中只占一个 bit,内存节省了 32 倍。

不仅如此,Bitmap 在用户群做交集和并集运算的时候也有极大的便利。


位运算:

&

0000000110B & 00000000010B = 0000000010B

|

0000000110B | 000000001000B = 0000001110B


<<

a shl b就表示把a转为二进制后左移b位(在后面添b个0)。例如100的二进制为1100100,而110010000转成十进制是400,那么100 shl 2 = 400。可以看出,a shl b的值实际上就是a乘以2的b次方,因为在二进制数后添一个0就相当于该数乘以2。


Bitmap 算法的另一个优势:位运算的高性能


缺点:不支持【非运算】

如何求出呢?我们可以使用异或操作,即相同位为0,不同位为1

OR是或运算,A OR B的结果:当A、B中只要有一个或者两个都为1时,结果为1,否则为0

XOR是异或运算,A XOR B的结果:当A、B两个不同时结果为1,否则为0

0000000110B XOR 0000001110B = 0000001000B


一个疑问:如果在一个很长的 Bitmap 里只存有一两个用户,那样岂不是很浪费空间。


Bitmap 算法的优势:

(1)节省内存。

(2)位运算的高性能。


你可能感兴趣的:(算法)