位图
用某一位表示存储的状态
位图的适用场景
举个栗子
以 byte[] 数组为例
byte[] 数组中元素的大小是 1 Byte(字节), 8 bit(比特位)
存在数组 int[] arr = {1, 4, 12, 20}
满足数据为自然数(≥ 0), 数据不重复
存入 byte[] 数组
对于 byte[] bytes
用某一位表示存储的状态
此处利用 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(int val)
将某一位设置为 1
(将 val 存储至位图中)
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(int val)
判断当前位是否为 1
(判断 val 在位图中是否存在)
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(int val)
将某一位设置为 0
(将 val 从位图中删除)
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()
获取位图中的元素个数
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 判断是否存储了该数字
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
创作不易,如果对您有帮助,希望您能点个免费的赞
大家有什么不太理解的,可以私信或者评论区留言,一起加油