BitSet—位图

news/2024/11/28 21:56:33/

BitSet

  • 🔎概念
  • 🔎位图的模拟实现
    • set()
    • get()
    • reSet()
    • getUsedSize()
    • 完整代码
  • 🔎利用位图进行排序
  • 🔎结尾

🔎概念


位图
用某一位表示存储的状态

位图的适用场景

  • 海量数据
  • 数据为自然数(≥ 0)
  • 数据不重复

举个栗子🌰

以 byte[] 数组为例
byte[] 数组中元素的大小是 1 Byte(字节), 8 bit(比特位)

在这里插入图片描述

存在数组 int[] arr = {1, 4, 12, 20}
满足数据为自然数(≥ 0), 数据不重复
存入 byte[] 数组

在这里插入图片描述

  • 对于 byte[] bytes

    • bytes[0] 用于存储 0 ~ 7 之间的数字
    • bytes[1] 用于存储 8 ~ 15 之间的数字
    • bytes[2] 用于存储 16 ~ 23 之间的数字
  • 用某一位表示存储的状态

    • 用 bytes[0] 的第 0 ~ 7 位(比特位)表示是否存储 0 ~ 7 之间的数字
    • 用 bytes[1] 的第 0 ~ 7 位(比特位)表示是否存储 8 ~ 15 之间的数字
    • 用 bytes[2] 的第 0 ~ 7 位(比特位)表示是否存储 16 ~ 23 之间的数字

🔎位图的模拟实现


此处利用 byte[] 数组模拟实现位图

定义两个变量
public byte[] bytes表示位图
public int usedSize表示位图中的元素个数

无参的构造方法🍭

public ExBitSet() {this.bytes = new byte[1];
}

带参的构造方法🍭

n 表示位数
8 表示byte[] 数组的大小为1 Byte(字节), 8 bit(比特位)
n / 8 +1
(0 ~ 7 之间的数字 / 8 = 0, 但所需的大小为 1 字节 → 存储 0 ~ 7 之间的数字)

public ExBitSet(int n) {this.bytes = new byte[n / 8 + 1];
}

set()


set(int val)
将某一位设置为 1
(将 val 存储至位图中)

  • val 表示传入的数字, 在 byte[] 数组中根据该数字的值修改其对应下标的位
  • arrayIndex 表示 bytes 数组的下标
  • bitIndex 表示对应的位
public void set(int val) {if(val < 0) {throw new ValException("val 值小于0");}int arrayIndex = val / 8;if(arrayIndex > bytes.length) {bytes = Arrays.copyOf(bytes, arrayIndex + 1);}int bitIndex = val % 8;bytes[arrayIndex] |= 1 << bitIndex;usedSize++;
}

举个栗子🌰

val = 12
arrayIndex = 12 / 8 = 1(对应 byte[] 数组的下标为1 → bytes[1])
bitIndex = 12 % 8 = 4(对应的位数为4 → 下标为1, 第 4 位表示 1 * 8 + 4 = 12)

bytes[arrayIndex] |= 1 << bitIndex
将 bytes[1] 的第 4 位设置为 1, 表示存储了数字 12

在这里插入图片描述
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

在这里插入图片描述

get()


get(int val)
判断当前位是否为 1
(判断 val 在位图中是否存在)

  • val 表示传入的数字, 在 byte[] 数组中根据该数字的值修改其对应下标的位
  • arrayIndex 表示 bytes 数字的下标
  • bitIndex 表示对应的位
public boolean get(int val) {if(val < 0) {throw new ValException("val 值小于0");}int arrayIndex = val / 8;if(arrayIndex > bytes.length) {bytes = Arrays.copyOf(bytes, arrayIndex + 1);}int bitIndex = val % 8;return (bytes[arrayIndex] & 1 << bitIndex) != 0;
}

举个栗子🌰

val = 12
arrayIndex = 12 / 8 = 1(对应 byte[] 数组的下标为1 → bytes[1])
bitIndex = 12 % 8 = 4(对应的位数为4 → 下标为1, 第 4 位表示 1 * 8 + 4 = 12)

bytes[arrayIndex] &= 1 << bitIndex
若存储了数字12, 则 bytes[1] 的第 4 位为 1

在这里插入图片描述

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

在这里插入图片描述

reSet()


reSet(int val)
将某一位设置为 0
(将 val 从位图中删除)

  • val 表示传入的数字, 在 byte[] 数组中根据该数字的值修改其对应下标的位
  • arrayIndex 表示 bytes 数字的下标
  • bitIndex 表示对应的位
public void reSet(int val) {if(val < 0) {throw new ValException("val 值小于0");}int arrayIndex = val / 8;if(arrayIndex > bytes.length) {bytes = Arrays.copyOf(bytes, arrayIndex + 1);}int bitIndex = val % 8;bytes[arrayIndex] &= ~(1 << bitIndex);usedSize--;
}

举个栗子🌰

val = 12
arrayIndex = 12 / 8 = 1(对应 byte[] 数组的下标为1 → bytes[1])
bitIndex = 12 % 8 = 4(对应的位数为4 → 下标为1, 第 4 位表示 1 * 8 + 4 = 12)

bytes[arrayIndex] &= ~(1 << bitIndex)
将 bytes[1] 的第 4 位设置为 0, 表示删除了数字 12

在这里插入图片描述

~0 = 1
~1 = 0

在这里插入图片描述

getUsedSize()


getUsedSize()
获取位图中的元素个数

public int getUsedSize() {return usedSize;
}

完整代码


这里的异常是自定义的
也可以根据自己的需要进行相关的修改

import java.util.Arrays;public class ExBitSet {public byte[] bytes;// 记录当前位图中存在多少个有效数据public int usedSize;public ExBitSet() {this.bytes = new byte[1];}/*** n → 需要多少位*/public ExBitSet(int n) {this.bytes = new byte[n / 8 + 1];}/*** 设置某一位为 1*/public void set(int val) {if(val < 0) {throw new ValException("val 值小于0");}int arrayIndex = val / 8;if(arrayIndex > bytes.length) {bytes = Arrays.copyOf(bytes, arrayIndex + 1);}int bitIndex = val % 8;bytes[arrayIndex] |= 1 << bitIndex;usedSize++;}/*** 判断当前位是否为 1*/public boolean get(int val) {if(val < 0) {throw new ValException("val 值小于0");}if(arrayIndex > bytes.length) {bytes = Arrays.copyOf(bytes, arrayIndex + 1);}int arrayIndex = val / 8;int bitIndex = val % 8;return (bytes[arrayIndex] & 1 << bitIndex) != 0;}/*** 将对应位置变为0*/public void reSet(int val) {if(val < 0) {throw new ValException("val 值小于0");}if(arrayIndex > bytes.length) {bytes = Arrays.copyOf(bytes, arrayIndex + 1);}int arrayIndex = val / 8;int bitIndex = val % 8;bytes[arrayIndex] &= ~(1 << bitIndex);usedSize--;}// 当前位图中的元素个数public int getUsedSize() {return usedSize;}}

🔎利用位图进行排序


根据 byte[] 数组的下标计算数据所在的范围区间
根据当前位是否为 1 判断是否存储了该数字

  • bytes[0] 表示 0 ~ 7 之间的数字(0 * 8 + 对应的位)
  • bytes[1] 表示 8 ~ 15 之间的数字(1 * 8 + 对应的位)
  • bytes[2] 表示 16 ~ 23 之间的数字(2 * 8 + 对应的位)
public static void main(String[] args) {ExBitSet bitSet = new ExBitSet();int n = bitSet.bytes.length;for(int i = 0; i < n; i++) {int x = bitSet.bytes[i];for(int j = 0; x != 0 && j < 8; j++) {if((x & 1 << j) != 0) {System.out.println(i * 8 + j);}}}
}

举个栗子🌰

假设当前位图中存储的元素为 1, 12, 4, 0, 23, 5

  • int n = 3
  • bytes[0] != 0, bytes[1] != 0, bytes[2] != 0
  • i 表示对应的下标, i * 8 表示对应的取值范围
  • j 表示对应的位数, i * 8 + j 表示具体的数值

在这里插入图片描述

🔎结尾

创作不易,如果对您有帮助,希望您能点个免费的赞👍
大家有什么不太理解的,可以私信或者评论区留言,一起加油


http://www.ppmy.cn/news/340038.html

相关文章

达人评测:华为手环b6和b5有什么区别?哪个好?优缺点曝光真相

华为手环b6与b5的区别介绍 一、基本参数对比 华为手环b6和b5这两款手机具体参数规格和用户评价参考看下官方旗舰店的‘商品评价’&#xff0c;链接帮贴上了 华为手环b6更多使用感受和评价&#xff1a;https://www.jd.shouji.com/b6 华为手环b5更多使用感受和评价&#xff1a;…

java 获取类里面的属性和函数方法,并运行类的函数方法

助手类&#xff0c;获取类里面的属性和函数 import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List;//TODO 获取类里面的属性和函数方法 public class ClassUtils {//TODO 获取类里面…

flutter自定义系列之简单的K线图绘制

上篇文章讲了flutter自定义的相关流程&#xff0c; 今天继续练习下flutter的自定义K线&#xff1a; 我们可以通过自定义Painter来实现一个简单的K线图界面&#xff1a; 创建一个自定义的Painter&#xff0c;用于绘制K线图&#xff1a; import dart:ui;import package:flutte…

华为OD机试真题 JavaScript 实现【勾股数元组】【2022Q4 100分】,附详细解题思路

一、题目描述 如果三个正整数A、B、C ,ABC则为勾股数 如果ABC之间两两互质&#xff0c;即A与B&#xff0c;A与C&#xff0c;B与C均互质没有公约数&#xff0c; 则称 其为勾股数元组。 请求出给定n~m范围内所有的勾股数元组。 二、输入描述 起始范围 1 < n < 10000 n &…

Mysql中explain的用法详解

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

Python内存管理与垃圾回收深度解析

Python的内存管理和垃圾回收是一项基础但至关重要的技术。理解Python如何管理内存可以帮助我们写出更优化、更高效的代码&#xff0c;同时也可以帮助我们更好地理解Python运行时的一些行为。在本文中&#xff0c;我们将深入探讨Python的内存管理和垃圾回收机制。 一、Python的…

20230612 set1打卡

哈希表理论基础 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

人工智能体系和实战指南

前言 人工智能是一个庞大的研究领域。虽然我们已经在人工智能的理论研究和算法开发方面取得了一定的进展&#xff0c;但是我们目前掌握的能力仍然非常有限。机器学习是人工智能的一个重要领域&#xff0c;它研究计算机如何模拟或实现人类的学习行为&#xff0c;以获取新的知识或…