Shallow Dream

Keep It Simple and Stupid!

0%

位图

位图,用比特来存储信息

一个简单的例子,假如你有一个整数集合,然后给你一些数

要求能够实现两个功能

  • add(num):加一个数
  • contain(num):判断一个数是否属于该集合。

首先可以想到哈希表,然后进行存储,查询,但是存一个int类型的数至少就是4个字节

利用位图我们就可以减少存储需要的空间

如果我们事先知道需要存储的数的大致范围,比如 0~31

我们就可以用一个整数来表示,因为一个整数是4字节,32位,每一位,我们用来表示0 ~ 31

存储数n,我们就可以,将对应位置1

image-20221110215355202

查询时只需要查询对应位置是否为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;

// 以最大值max 构造BitMap
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");
}