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);

    }
}

posted @ 2020-07-31 16:08  大嘤熊  阅读(292)  评论(0)    收藏  举报