位图
位图
-
用 bit 组成的数组来存放值,用 bit 状态 1,0 代表存在不存在,取值和存值都用位运算。限制是必须为连续范围且不能过大。
-
实现
// 初始化位图大小,只支持 0 ~ n - 1 所有数字的增删改查
void Bitset(int n);
void add(int num);
void remove(int num);
// 如果位图里没有 num,就加入;如果有就删除
void reverse(int nums);
bool contains(int num);
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
vector<int> st;
// 初始化位图大小,只支持 0 ~ n - 1 共 n 个数字的增删改查
void Bitset(int n) {
// a / b 的结果向上取整:(a + b - 1) / b,前提都是正数
st.resize((n + 31) / 32);
}
// 加入位图
// 下标从 0 开始,num 在编号为 num / 32 的 32 位 int 中,下标为 num % 32
// 1 << (num % 32) 表示把 1 左移 (num % 32) 位
void add(int num) {
st[num / 32] |= 1 << (num % 32);
}
// 删除
void remove(int num) {
st[num / 32] &= ~(1 << (num % 32));
}
// 如果位图里没有 num,就加入;如果有就删除
void reverse(int num) {
st[num / 32] ^= 1 << (num % 32);
}
// 是否包含
bool contains(int num) {
return ((st[num / 32] >> (num % 32)) & 1) == 1;
}
int main() {
int n = 1000;
int testTimes = 10000;
// 位图,范围 0~999
Bitset(n);
// 自带的 set 进行对比测试
unordered_set<int> hashSet;
srand(time(NULL));
for (int i = 0; i < testTimes; ++i) {
double decide = rand() / (double) (RAND_MAX);
// 范围 0~999
int number = rand() % (n - 1);
if (decide < 0.333) {
add(number);
hashSet.emplace(number);
} else if (decide < 0.666) {
remove(number);
hashSet.erase(number);
} else {
reverse(number);
if (hashSet.find(number) == hashSet.end())
hashSet.emplace(number);
else
hashSet.erase(number);
}
}
bool flag = true;
for (int i = 0; i < 1000; ++i) {
if (contains(i) != (hashSet.find(i) != hashSet.end())) {
flag = false;
break;
}
}
cout << boolalpha << flag;
}
2166. 设计位集
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
class Bitset {
public:
vector<int> st;
int len;
bool reversed = false;
int oneCount = 0;
int zeroCount;
Bitset(int size) {
len = size;
zeroCount = size;
st.resize((size + 31) / 32);
}
bool isOne(int idx) {
return (st[idx / 32] & (1 << (idx % 32))) != 0;
// return ((st[idx / 32] >> (idx % 32)) & 1) == 1;
}
void fix(int idx) {
if ((!reversed && !isOne(idx))
|| reversed && isOne(idx)) {
zeroCount--;
oneCount++;
reverse(idx);
}
}
void unfix(int idx) {
if ((!reversed && isOne(idx))
|| reversed && !isOne(idx)) {
zeroCount++;
oneCount--;
reverse(idx);
}
}
/* void fix(int idx) {
int index = idx / 32;
int bit = idx % 32;
if (!reversed) {
// 含义没反转,改成 1
if (!isOne(idx)) {
// idx 位置不是 1 的时候才要修改
zeroCount--;
oneCount++;
st[index] |= (1 << bit);
}
} else {
// 含义反转,改成 0
if (isOne(idx)) {
// idx 位置是 1 的时候才要修改
zeroCount--;
oneCount++;
// st[index] &= ~(1 << bit);
st[index] ^= (1 << bit);
}
}
}*/
/* void unfix(int idx) {
int index = idx / 32;
int bit = idx % 32;
if (!reversed) {
// 含义没反转,改成 0
if (isOne(idx)) {
zeroCount++;
oneCount--;
// st[index] &= ~(1 << bit);
st[index] ^= (1 << bit);
}
} else {
// 含义反转,改成 1
if (!isOne(idx)) {
zeroCount++;
oneCount--;
st[index] |= (1 << bit);
}
}
}*/
void reverse(int idx) {
st[idx / 32] ^= (1 << (idx % 32));
}
// 数组中每个位其实没有反转,只是含义反转了
void flip() {
reversed = !reversed;
swap(oneCount, zeroCount);
}
bool all() {
return oneCount == len;
}
bool one() {
return oneCount > 0;
}
int count() {
return oneCount;
}
string toString() {
string s;
for (int i = 0; i < len; ++i) {
char ch = '0';
if ((reversed == false && isOne(i))
|| (reversed == true && !isOne(i)))
ch = '1';
s.append(1, ch);
}
return s;
}
};