位图
位图
-
用 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; } };
本文作者:n1ce2cv
本文链接:https://www.cnblogs.com/sprinining/p/18417080
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-09-17 Git