BitMap算法
1.1 简介
bitmap是一个十分有用的结构。所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此可以大大节省存储空间。
1.2基本思想
假如我们有一万个数据 (假设我们这里是int型数据),需要判断重复,简单暴力点双重循环解决,这种方法很慢。当然进一步可以采用set集合。确实时间复杂度降低了。但是如果数据量再大点呢,比如10亿。我们就可以采取BitMap思想来解决。首先确定数据中的最大值max。然后申请一个长度为max的数组来进行标记。如果存在就标记一下。考虑到Java中int占32bit。我们就可以申请一个int[max/32+1]数组进行标记。默认为0不存在。遍历到数据后标记为1。
1.3重点
如何确定数据和bit—map的映射关系。
我们要把一个整数N映射到Bit-Map中去,首先要确定把这个N Mapping到哪一个数组元素中去,即确定映射元素的index。我们用int类型的数组作为map的元素,这样我们就知道了一个元素能够表示的数字个数(这里是32)。于是N/32就可以知道我们需要映射的key了。所以余下来的那个N%32就是要映射到的位数。
求十进制数对应在数组a中的下标:
- 先由十进制数n转换为与32的余可转化为对应在数组a中的下标。位运算更快
int index = n/32=n/(2^5)=n>>5 - 求十进制数对应数组元素a[i]在0-31中的位m。位运算更快
m= n%32 = n&31 = n&((1<<5)-1) = n & 0x1F - 置一操作 或运算巧用
a[i] = a[i] | (1<<m)
1.4代码
package bitmap;
/**
* JavaTest
*
* @author : xgj
* @description : 自定义bitmap
* @date : 2020-07-31 15:55
**/
public class BitMap {
public static final int MAX_VALUE = Integer.MAX_VALUE;
public int maxValue;
private int[] a;
public BitMap() {
maxValue = MAX_VALUE;
}
public BitMap(int maxValue) {
this.maxValue = maxValue;
}
private void initTables(int maxValue) {
int size = maxValue >> 5;
a = new int[ size + 1];
}
/**
* 功能描述 增加元素
*
* @param n
* @return void
* @author xgj
* @date 2020/7/31
*/
public void addValue(int n) {
if (a == null) {
initTables(maxValue);
}
if (n < 0 || n > maxValue) {
System.out.println("不再0到" + maxValue + "的范围内,不能加入");
return;
}
//n对应数组的哪个元素,是n/32
int row = n >> 5;
//n对应的int中的位置,是n mod 32
int index = n & 0x1F;
//在n对应的int,对应的位置,置1
a[row] |= 1 << index;
}
/**
* 功能描述 :
*
* @param n
* @return boolean
* @author xgj
* @date 2020/7/31
*/
public boolean existValue(int n) {
if (n < 0 || n > maxValue) {
System.out.println("不再0到" + maxValue + "的范围内,一定没有");
return false;
}
//n对应数组的哪个元素,是n/32
int row = n >> 5;
//n对应的int中的位置,是n mod 32
int index = n & 0x1F;
//result为哪个位置上现在保存的值(为10000(index个0)或者0)
int result = a[row] & (1 << index);
//如果不为0,则那个位置一定为1
return result != 0;
}
/**
* 功能描述 :
*
* @param n
* @return void
* @author xgj
* @date 2020/7/31
*/
public void removeValue(int n) {
if (n < 0 || n > maxValue) {
System.out.println("不再0到" + maxValue + "的范围内,一定没有");
return;
}
//n对应数组的哪个元素,是n/32
int row = n >> 5;
//n对应的int中的位置,是n mod 32
int index = n & 0x1F;
//对应位置0,与 111101111进行与运算,那位一定变0
a[row] &= ~(1 << index);
}
public void displayRow(int row) {
int countNumber = row*32+1;
if (countNumber < 0 || countNumber> maxValue) {
System.out.println("不再0到" + maxValue + "的范围内,一定没有");
} else {
System.out.print("bitmap展示第" + row + "行:" + Integer.toBinaryString(a[row]) + " 有:");
//对应row:32*row到32*row+31
int now = row << 5;
//temp为与对应位进行与运算的数字
int temp = 1;
for (int i = 0; i < 32; i++) {
int result = a[row] & temp;
if (result != 0) {
System.out.print(" " + now + " ");
}
now++;
temp = temp << 1;
}
System.out.println();
}
}
}
package ztext;
import bitmap.BitMap;
import java.util.Arrays;
/**
* @author xgj
*/
public class MyTest {
public static void main(String[] args) {
BitMap b1 = new BitMap(100);
b1.addValue(20);
b1.addValue(50);
b1.displayRow(0);
b1.displayRow(1);
}
}

浙公网安备 33010602011771号