package class05; import java.util.HashSet; /** * 用位图存储数字,而不是使用int[] 数组, 这样能大大节省空间, 最少节省32倍空间。 * 这里使用long[] 表示位图, 每个long能存储64个数字,如果数组长度为10,那么能存储640个数字, 存储数字范围从1到640,是连续的数字范围 * 注意:这里的每一位表示一个数字,不会用2位或者多位表示一个存储的数字 * 每一位的位置表示一个数字,比如第640位表示数字640 * 最重要的两种计算是 取余 和 取模, 并且 取余和取模 都用位运算实现 * 记住,取模主要就是用于确定位置,例如hashMap中确定数组下标,就是一个确切的位置,在这里也是如此 */ public class Code01_BitMap1 { public static class BitMap { private long[] bits; //构造器 /** * * @param max, 表示要存储多少个数字 */ public BitMap(int max) { bits = new long[(max + 64) >> 6]; } /** * 1L << (num & 63) 定位到要操作的那一位,然后按位或。 * num & 63 取模运算(Note: 只有在对特定值(2^n)取模的时候,才能使用这种方式,其它情况下是错误的) * num & 63 等价于num % 64,由于位运算速度快,所以我们使用位运算 * Note: 只有在对特定值(2^n)取模的时候,才能使用这种方式,其它情况下是错误的 * * 取余运算 num >> 6 等价于 num / 64 * Note: 只有在对特定值(2^n)取余的时候,才能使用这种方式,其它情况下是错误的 * @param num */ public void add(int num) { bits[num >> 6] |= (1L << (num & 63)); } /** * 1L << (num & 63) 定位到要操作的那一位,然后处理。 num & 63 取模运算(Note: 只有在对特定值(2^n)取模的时候,才能使用这种方式,其它情况下是错误的) * Note: 只有在对特定值(2^n)取模的时候,才能使用这种方式,其它情况下是错误的 * * 取余运算 num >> 6 等价于 num / 64 * Note: 只有在对特定值(2^n)取余的时候,才能使用这种方式,其它情况下是错误的 * @param num */ public void delete(int num) { bits[num >> 6] &= ~(1L << (num & 63)); } /** * 1L << (num & 63) 定位到要操作的那一位,然后处理。 num & 63 取模运算(Note: 只有在对特定值(2^n)取模的时候,才能使用这种方式,其它情况下是错误的) * Note: 只有在对特定值(2^n)取模的时候,才能使用这种方式,其它情况下是错误的 * * 取余运算 num >> 6 等价于 num / 64 * Note: 只有在对特定值(2^n)取余的时候,才能使用这种方式,其它情况下是错误的 * @param num * @return */ public boolean contains(int num) { return (bits[num >> 6] & (1L << (num & 63))) != 0; } } public static void main(String[] args) { System.out.println("测试开始!"); int max = 10000; BitMap bitMap = new BitMap(max); HashSet<Integer> set = new HashSet<>(); int testTime = 10000000; 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("Oops!"); break; } } } for (int num = 0; num <= max; num++) { if (bitMap.contains(num) != set.contains(num)) { System.out.println("Oops!"); } } System.out.println("测试结束!"); } }
位运算 - 位图存储数字(替代数组)
于 2022-02-26 12:47:49 首次发布