位图,用比特来存储信息
一个简单的例子,假如你有一个整数集合,然后给你一些数
要求能够实现两个功能
- add(num):加一个数
- contain(num):判断一个数是否属于该集合。
首先可以想到哈希表,然后进行存储,查询,但是存一个int类型的数至少就是4个字节
利用位图我们就可以减少存储需要的空间
如果我们事先知道需要存储的数的大致范围,比如 0~31
我们就可以用一个整数来表示,因为一个整数是4字节,32位,每一位,我们用来表示0
~ 31
存储数n,我们就可以,将对应位置1
查询时只需要查询对应位置是否为1,即可判断目标数是不是在集合中
如果存储数的范围大了很多呢?
0~1023
我们可以就可以用一组整数来存储,一个int可以存储32个数,那么1024个数,就需要1021
/ 32 = 32组
int[32] set
set[1] 存储0 ~ 31
set[2] 存储32~63
...
位图的实现
做一个集合,确定最大值
位图的优点
极大的压缩空间
代码部分
位图实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class BitMap { private long[] bits;
public BitMap(int max) { bits = new long[(max + 64) >> 6]; }
public void add(int num) { bits[num >> 6] |= 1L << (num & 63); }
public void delete(int num) { bits[num >> 6] &= ~(1L << (num & 63)); }
public boolean contains(int num) { return (bits[num >> 6] & (1L << (num & 63))) != 0; } }
|
对数器部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public static void main(String[] args) { System.out.println("Start!"); int max = 10000; HashSet<Integer> set = new HashSet<>(); BitMap bitMap = new BitMap(max);
int testTime = 100000; for (int i = 0; i < testTime; i++) { int num = (int) (Math.random() * max + 1); double decide = Math.random(); if (decide < 0.333) { bitMap.add(num); set.add(num); } else if (decide < 0.666) { bitMap.delete(num); set.remove(num); } else { if (bitMap.contains(num) != set.contains(num)) { System.out.println("WA"); break; } } }
for (int num = 0; num <= max; num++) { if (bitMap.contains(num) != set.contains(num)) { System.out.println("WA"); break; } }
System.out.println("Fin"); }
|