位图实现及应用

⭐️前言⭐️

本文主要讲述高阶数据结构位图的实现及应用,位图通常适用于海量数据,整数,数据无重复的场景,通常是用来判断某个数据存不存在的。

🍉欢迎点赞 👍 收藏留言评论

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传GitHub


📍内容导读📍

  • [🍅 1、位图概念](#🍅 1、位图概念)
  • [🍅 2、位图实现](#🍅 2、位图实现)
  • [🍅 3、位图排序](#🍅 3、位图排序)
  • [🍅 4、位图应用](#🍅 4、位图应用)

🍅 1、位图概念

首先先引入一道面试题,给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。【腾讯】

解决这道题目,有以下几种解决方案:
1、遍历,时间复杂度是O(N)
2、先排序O(N*logN) 再二分查找 O(logN)

以上两种解法都是能想到的较好的解决方法,但是我们的题目中有一个前提条件是40亿个数据,如果是小体量的数据,用我们刚刚提出的两种解法,都能够解决;但是面对如此大规模的数据,光是存储到内存就不太可能实现。

所以我们可以用位图来解决这样的问题:

数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如:

所谓位图,就是用每一位来存放某种状态,适用于海量数据,整数,数据无重复的场景。通常是用来判断某个数据存不存在的。

如上例子,10个整数本应该存放需要40个字节,此时用位图只需要3个字节。

🍅 2、位图实现

以下是位图的实现:

java 复制代码
import java.util.Arrays;

public class MyBitSet {
    private byte[] elem;
    public int usedSize;

    public MyBitSet() {
        // 默认只给一个大小
        elem=new byte[1];
    }

    /**
     * n个比特位
     * @param n
     */
    public MyBitSet(int n) {
        elem=new byte[n/8+1];
    }

    /**
     * 将数据的对应位置置为1
     * @param val
     */
    public void set(int val) {
        if(val<0) {
            throw new IndexOutOfBoundsException();
        }
        int arrayIndex=val/8;
        // 扩容
        if(arrayIndex>elem.length-1) {
            elem= Arrays.copyOf(elem,arrayIndex+1);
        }
        int bitIndex=val%8;
        this.elem[arrayIndex] |= (1<<bitIndex);
        usedSize++;
    }

    /**
     * 测试该数字是否存在
     * @param val
     * @return
     */
    public boolean get(int val) {
        if(val<0) {
            throw new IndexOutOfBoundsException();
        }
        int arrayIndex=val/8;
        // 扩容
        if(arrayIndex>elem.length-1) {
            elem= Arrays.copyOf(elem,arrayIndex+1);
        }
        int bitIndex=val%8;
        // 判断 elem[index]的对应位是不是1,是的话按位与的结果是不等于0的
        if((this.elem[arrayIndex]&(1<<bitIndex))!=0) {
            return true;
        }
        return false;
    }

    /**
     * 将数据对应位置 置为0
     * @param val
     */
    public void reSet(int val) {
        if(val<0) {
            throw new IndexOutOfBoundsException();
        }
        int arrayIndex=val/8;
        int bitIndex=val%8;
        this.elem[arrayIndex]&=~(1<<bitIndex);
        usedSize--;
    }

    /**
     * 当前比特位有多少个1
     * @return
     */
    public int getUsedSize() {
        return this.usedSize;
    }

    public static void main(String[] args) {
        int[] array={1,2,3,10,4,18,13};
        MyBitSet myBitSet=new MyBitSet(18);
        for (int i = 0; i < array.length; i++) {
            myBitSet.set(array[i]);
        }
        System.out.println(myBitSet.getUsedSize());
        System.out.println(myBitSet.get(10));
        myBitSet.reSet(10);
        System.out.println(myBitSet.get(10));
    }
}

在Java中,也有对应的集合类BitSet实现了类图

java 复制代码
  	public static void main1(String[] args) {
        int[] array = {1,2,3,10,4,18,13};
        BitSet bitSet = new BitSet(18);
        for (int i = 0; i < array.length; i++) {
            bitSet.set(array[i]);
        }
        System.out.println(bitSet.get(100));
    }

🍅 3、位图排序

通过位图中数据的存放逻辑,我们看图片也能结合推断出,如果按照分区按序打印,也能够实现数据的去重排序

因为每个数字是否存在,在位图中都有体现,分区遍历判断每一位是否存在,如果存在就打印,即可实现去重排序,具体的排序代码可以见下:

java 复制代码
 	public static void main3(String[] args) {
        int[] array = {1,3,2,13,10,3,14,18,3};
        MyBitSet myBitSet = new MyBitSet(18);
        for (int i = 0; i < array.length; i++) {
            myBitSet.set(array[i]);
        }

        for (int i = 0; i < myBitSet.elem.length; i++) {
            for (int j = 0; j < 8; j++) {
                if((myBitSet.elem[i] & (1 << j) ) != 0 ) {
                    System.out.println(i*8+j);
                }
            }
        }
    }

🍅 4、位图应用

  1. 快速查找某个数据是否在一个集合中
  2. 排序 + 去重
  3. 求两个集合的交集、并集等
  4. 操作系统中磁盘块标记

⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

相关推荐
️南城丶北离1 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻1 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
菜鸡中的奋斗鸡→挣扎鸡8 小时前
滑动窗口 + 算法复习
数据结构·算法
axxy20009 小时前
leetcode之hot100---240搜索二维矩阵II(C++)
数据结构·算法
Uu_05kkq11 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
1nullptr13 小时前
三次翻转实现数组元素的旋转
数据结构
TT哇13 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
A懿轩A13 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
1 9 J14 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
汝即来归14 小时前
选择排序和冒泡排序;MySQL架构
数据结构·算法·排序算法