位图的实现

前言:      

hashset,用来存储key,天然帮你去重了,比如存储5,6,8,int类型的数,然后hashset可以查看5在不在这个集合中,但是int是4byte,32bit,用一个4字节的存储才能判断某个数在不在,用32位的一个空间才能表示一个数字在不在hash表里面,更不用说hash表自己内部还有别的空间消耗,这就非常的浪费空间。
这就引入了位图的概念。位图是什么呢?也许这个数的范围非常有限,此时就可以不用hash表,用更省空间的位图的方式。例如已知所有的数字是从0~10000,一个数字进来就耗4字节,太费了。

 

假设arr数组,里面有a,b,c,d...,a可以表示0~31这些数字有没有出现;b可以表示32~63这些数字有没有出现...比如1出现了,那么就在a的0位上标1。
那么要表示0~1000这些数有没有出现,至少需要几个数字呢?需要:1000/32个数字,即arr数组的长度为1000/32。
 
 

 

1、位图的实现思路:

package com.cy.code;

/**
 * 位图的实现
 * Bitset是一种能以紧凑形式存储位的数据结构
 * Bitset(int n): 初始化n个位,所有位都是0
 * void fix(int i): 将下标i的位上的值更新为1
 * void unfix(int i): 将下标i的位上的值更新为0
 * void flip(): 翻转所有位的值
 * boolean all(): 是否所有的位都是1
 * boolean one(): 是否至少有一位是1
 * int count(): 返回所有位中1的数量
 * String toString(): 返回所有位的状态
 * 测试连接:https://leetcode-cn.com/problems/design-bitset/
 */
public class Code08_DesignBitsetTest {

    /**
     * 一、查询
     * 假设数组长度为400,请问400这个数有没有出现?
     * 400应该是在数组的下标位置:400 / 32
     * 在第几位呢?400 % 32
     * 再右移这么多位得到一个数
     * 再和1进行&运算,得到0或1, 0表示不存在,1表示存在
     *
     * 二、修改
     * 怎么让num进入位图,在相应的位置上标1,如果之前就是1,那就维持1
     * 先定位到数组的下标: arr[num / 32]
     * 改数组的这个数的哪一位呢? num % 32
     * 再将1左移这么多位得到结果,再将这个结果与原数组的数arr[num / 32]进行或运算
     *
     * 三、删除
     * 怎么让num进入位图,在相应的位置上标记0
     */
    public static void main(String[] args) {
        // arr[0] -> 0  ~ 31
        // arr[1] -> 32 ~ 63
        int[] arr = new int[400];
        int num = 400;
        int status = (arr[num / 32] >> (num % 32)) & 1;

        // 修改,num加入到arr中,如果之前有的话,就继续维持
        arr[num / 32] = arr[num / 32] | (1 << (num % 32));
        arr[num / 32] |= 1 << (num % 32);

        //修改,num从arr中删除
        arr[num / 32] = arr[num / 32] & (~(1 << (num % 32)));
    }
}

删除,怎么让num进入位图,在相应的位置上标记0呢?

思路草图:

 

二、位图的代码实现:

 

 

 

 

 

 

 

 

--

posted on 2025-03-31 22:10  有点懒惰的大青年  阅读(13)  评论(0)    收藏  举报