BitMap算法

探讨在有限内存条件下,使用BitMap算法高效判断一个数是否存在于40亿个整数集合中,通过位操作实现内存节约。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看一个场景:如何判断一个数是否在40亿个整数中?

题目:给一台普通PC,2G内存。我有40亿个整数,再给一个新的整数,我需要判断新的整数是否在40亿个整数中,你会怎么做?

分析:

40亿个int占(40亿*4字节)/1024/1024/1024 大概为16G左右,很明显内存只有2G,放不下,因此不可能将这40亿数据放到内存中计算。要快速的解决这个问题最好的方案就是将数据搁内存了,所以现在的问题就在如何在2G内存空间以内存储着40亿整数。

判断一个数是否存在,其实只有两个状态,存在或者不存在,可以用一个位代表。这样我就申请40亿个位就好了,新的数转换成一个位,然后判断一下这个位是0还是1就行了。其实你可以想想,32位int的范围,总共就是2的32次方,大概42亿多点。所以你可以申请2的32次方个位。算一下需要多少内存呢?2的32次方个位,相当于2的29次方个字节,哇,才500MB,真是节省了不少内存呢。

BitMap思想:

一个byte是占8个bit,如果每一个bit的值就是有或者没有,也就是二进制的0或者1,如果用bit的位置代表数组值有还是没有,那么0代表该数值没有出现过,1代表该数组值出现过。不也能描述数据了吗?如下图:

再看代码之前,我们先搞清楚一个问题,一个数怎么快速定位它的索引号,也就是说搞清楚byte[index]的index是多少,position是哪一位。举个例子吧,例如add(14)。14已经超出byte[0]的映射范围,在byte[1]范围之类。那么怎么快速定位它的索引呢。如果找到它的索引号,又怎么定位它的位置呢。Index(N)代表N的索引号,Position(N)代表N的所在的位置号。

Index(N) = N/8 = N >> 3;

Position(N) = N%8 = N & 0x07;

基于上面的分析,我们写一个简单的BitMap的算法如下:
 

package bitmap;

public class BitMap {

	 //保存数据的 
	private byte[] bits;
	//能够存储多少数据
	private int capacity;
	
	public BitMap(int capacity){
		this.capacity = capacity;
		//1bit能存储8个数据,那么capacity数据需要多少个bit呢,capacity/8+1,右移3位相当于除以8
		bits = new byte[(capacity >>3 )+1];
		}
	
	public void add(int num){
		// num/8得到byte[]的index
		int arrayIndex = num >> 3;
		// num%8得到在byte[index]的位置
		int position = num & 0x07;
		//将1左移position后,那个位置自然就是1,然后和以前的数据做|,这样,那个位置就替换成1了。
		bits[arrayIndex] |= 1 << position;
		}
	
	public boolean contain(int num){
		// num/8得到byte[]的index
		int arrayIndex = num >> 3;
		// num%8得到在byte[index]的位置
		int position = num & 0x07;
		//将1左移position后,那个位置自然就是1,然后和以前的数据做&,判断是否为0即可
		return (bits[arrayIndex] & (1 << position)) !=0;
		}

	public void clear(int num){
		// num/8得到byte[]的index
		int arrayIndex = num >> 3;
		// num%8得到在byte[index]的位置
		int position = num & 0x07;
		//将1左移position后,那个位置自然就是1,然后对取反,再与当前值做&,即可清除当前的位置了.
		bits[arrayIndex] &= ~(1 << position);
	}
	

	public static void main(String[] args) {
		BitMap bitmap = new BitMap(100);
		bitmap.add(7);
		System.out.println("插入7成功");

		boolean isexsit = bitmap.contain(7);
		System.out.println("7是否存在:"+isexsit);

		bitmap.clear(7);
		isexsit = bitmap.contain(7);
		System.out.println("7是否存在:"+isexsit);

	}

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值