数据结构之位图
场景说明
现代计算数据量日趋壮大,比如一个int类型的数据占用4字节。假如我们要存储1亿个数,占用空间大小=4亿字节=390625M=381G
现在我们要在这1亿个数中随机搜索一个数。
问题分析
- 面对日趋增大的数据,想象通过硬件的升级去处理如此多的数据几乎不现实
- 这么大的数据 排序可能吗 答案是否定的
- 回归到计算机的组成原理。我们发现即使是1这个数也占用着4个字节的数据,是否有点浪费空间呢。
位图的出现
合理利用计算机的每一位就是它的目标。
- 假设我们使int数据的32位每一位都表示一个数。那么一个int就可以表示32个数。
代码再现
public class BitMap {
//最大的数
private int max;
int[] data;
public BitMap(int max) {
this.max=max;
data = new int[max/32+1];
}
//添加一个数
public void add(int num) {
int arrayIndex = num >> 5;// num/32
int dataIndex = num & 31; // num%32
int temp = data[arrayIndex];
System.out.println(num+" 添加之前,二进制表示:"+Integer.toBinaryString(data[arrayIndex]));
//注意用或
data[arrayIndex] = temp | ( 1 << dataIndex );// temp | 2^dataIndex
System.out.println(num+" 添加之后,二进制表示:"+Integer.toBinaryString(data[arrayIndex]));
}
//删除一个数
public void remove(int num) {
int arrayIndex = num >> 5;// num/32
int dataIndex = num & 31; // num%32
int temp = data[arrayIndex];
System.out.println(num+" 删除之前,二进制表示:"+Integer.toBinaryString(data[arrayIndex]));
//求反 2^dataIndex 之后出了dataIndex位置为0.其余都为1,这样在做与.
//dataIndex位置的值将改为0
data[arrayIndex] = temp & ~( 1 << dataIndex );// temp & ~(2^dataIndex)
System.out.println(num+" 删除之后,二进制表示:"+Integer.toBinaryString(data[arrayIndex]));
}
//搜索一个数
public void search(int num) {
int arrayIndex = num >> 5;// num/32
int dataIndex = num & 31; // num%32
int temp = data[arrayIndex];
int flag = temp & ( 1 << dataIndex );
//这里注意只需要大于0就好
if(flag > 0 ) {
System.out.println(num+" 已经被查询到");
return;
}
System.out.println(num+" 未被查询到");
}
public static void main(String[] args) {
BitMap bitMap = new BitMap(10000);
bitMap.add(12);
bitMap.add(65);
bitMap.add(122);
bitMap.add(123);
bitMap.add(14);
bitMap.add(500);
bitMap.add(502);
bitMap.search(122);
bitMap.search(500);
bitMap.remove(122);
bitMap.search(122);
bitMap.search(500);
}
}
总结
- 位图不能处理重复的数据。