【数据结构】位图的概念与实现

前言:

        在Java中,整型(int)的最大值MAX_VALUE = 2^31 - 1。而整型数组(int [ ])的下标是从0开始的,也就意味着一个整型数组最多存放2^31 - 1个元素。这种存储方式优点很明显:无论元素大小(不超过整型范围),每个元素所占的空间都是32位的,可以存下很大的数字;缺点是空间浪费的现象比较明显。

什么是位图?其原理是什么?

        位图(Bitset)是一种在整型数组的基础上充分利用空间的一种数据结构。其实就是利用bit位的取值来“存放值”,bit位是1代表元素存在、bit位是0代表元素不存在。每个bit位都可以代表一个元素,极大的节省了空间。

        由上图我们可以看到,如果我们初始化一个整型数组的长度为8,那么这个数组最多能存储的元素个数就是8;如果我们使用位图,每个索引下标都由32个bit位组成,每个bit位都能单独的表示一个元素是否存在,那么8个索引下标所能表示的元素个数是:32*8 = 256。

位图有什么缺点?

        位图的缺陷很明显,它只能表示连续的元素,需要在初始化位图时就声明它所能表示的元素范围

        如上图所示,虽然位图能存储的元素数量变得更多了,但它无法像整型数组那样随心所欲的存储任意元素(值不超过整型范围)。

如何实现位图?

        (1)构造位图:位图是基于整型数组实现的,所以成员变量需要一个整型数组;在创建位图时,需要声明它所能表示的元素范围,需要传递一个整型形参n,代表位图能表示的元素范围是:[0,n-1]。

        (2)添加元素:将表示元素的bit位设置成1。

        (3)移除元素:将表示元素的bit位设置成0。

        (4)“反转”元素:元素存在于位图中,则移除;元素不存在于位图中,则创建。

        (5)判断元素:判断元素是否存在于位图中。

        

如何验证位图的准确性?

        使用HashSet来验证位图是否真的能正确地添加、删除、“反转”元素。

        Code:

        int n = 1000;
        int testTimes = 10000;
        //位图能表示的元素范围:[0,999]
        BitSet bitSet = new BitSet(n);
        HashSet<Integer> hashSet = new HashSet<>();
        System.out.println("测试阶段开始");
        for (int i = 0; i < testTimes; i++) {
            //Math.random():生成一个double类型的值,范围在[0,1)之间
            double random = Math.random();//随机概率值
            //x的值在[0,1000)之间,不会超过位图所能表示的范围
            int x = (int) (Math.random() * n);//待添加的元素值
            if(random < 0.333){
                bitSet.add(x);
                hashSet.add(x);
            }else if(random < 0.666){
                bitSet.remove(x);
                hashSet.remove(x);
            }else{
                bitSet.reverse(x);
                if (hashSet.contains(x)){
                    hashSet.remove(x);
                }else {
                    hashSet.add(x);
                }
            }
        }
        System.out.println("验证阶段开始");
        for (int i = 0; i < n; i++) {
            if(bitSet.contains(i) != hashSet.contains(i))
                System.out.println("出错了");
        }
        System.out.println("验证阶段结束");

        执行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值