位图算法及实现
引入
对很多的数据进行操作会浪费巨大的内存,比如在40亿个无符号的整型数据,现在给定一个目标数字将其查找出来,一个整型int就是4个字节,10亿个int差不多已经需要4G的内存了,40亿个int就是16G。所以这里方法行不通的根本原因实际上是内存不够。而且如果对这40亿个整形数据进行排序,用到的内存会更多,因此需要有一种新的方法解决这个问题,这就是位图。
位图的应用
1、判断一个数是否存在某数据中
假如有40亿数据,我们如何快速判断指定一个数是否存在?
申请512M的内存 512M=512*1024*1024B*8=4294967296比特(bit) 这个空间可以装40亿了
一个bit位代表一个int值
读入40亿个数,设置相应的bit位
读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在
2、判断整形数组是否重复
它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到 5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。
3、给数组排序
首先遍历数组,得到数组的最大最小值,然后根据这个最大最小值来缩小bitmap的范围。这里需要注意对于int的负数,都要转化,而且取位的时候,数字要减去最小值。
public class WeiTu {
public static int[] bitmapSort(int[] arr) {
// 找出数组中最值
int max = arr[0];
int min = max;
for (int i : arr) {
if (max < i) {
max = i;
}
if (min > i) {
min = i;
}
}
//初始化位图数组大小
int temp=0;//用于解决数组有负数的情况
int[] newArr=null;
if(min<0){
temp=0-min;
newArr = new int[max - min + 1];
}else{
newArr = new int[max+1];
min=0;
}
//构建位图
for(int i:arr){
newArr[i+temp]++;//算法体现
}
// 重新调整arr数组中的元素
int index = 0;
for (int i = 0; i < newArr.length; i++) {
// 位图是1的就输出,对数组排序
while (newArr[i] > 0) {
arr[index] = i + min;
index++;
newArr[i]--;
}
}
return arr;
】 }
public static void main(String[] args) {
int[] arr={5,2,3,7,1};
//int[] arr={-5,2,-3,7,1};
int[] arrsort=bitmapSort(arr);
for(int i:arrsort)
System.out.println(i);
}
}
其实也就是用位置代替数字的大小,对于存在负数的情况,先将其加上某个数全变成正数,在排序完成后再减去加的这个数
4、判断某个字符是否在里面
ASCII码的长度呢是一个字节,共8位,虽然许多时候只谈128个,但理论上可以表示256个字符,因此可以用256容量的数组将字符转换为下标