位图的概念
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。
常见位图的应用:
快速查找某个数据是否在一个集合中。
求两个集合的交集、并集等。
位运算
& 与 :有0则为0,全为1则为1
| 或:有1则为1,全为0则为0
^ 异或:相同为0,相异为1
~ 按位取反
代码
BitSet.h
#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace lrf
{
template<unsigned int N>
class bitset
{
public:
bitset()
{
_a.resize(N / 32 + 1);
}
void set(size_t x)
{
size_t i = x / 32;
size_t j = x % 32;
_a[i] |= (1 << j);
}
void reset(size_t x)
{
size_t i = x / 32;
size_t j = x % 32;
_a[i] &= (~(1 << j));
}
bool test(size_t x)
{
size_t i = x / 32;
size_t j = x % 32;
return _a[i] & (1 << j);
}
private:
vector<int> _a;
};
template<size_t N>
class twobitset
{
public:
void set(size_t x)
{
// 00 -> 01
if (!_bs1.test(x) && !_bs2.test(x))
{
_bs2.set(x);
} // 01 -> 10
else if (!_bs1.test(x) && _bs2.test(x))
{
_bs1.set(x);
_bs2.reset(x);
}
// 本身10代表出现2次及以上,就不变了
}
bool is_once(size_t x)
{
return !_bs1.test(x) && _bs2.test(x);
}
private:
bitset<N> _bs1;
bitset<N> _bs2;
};
}
test.c
#include"BitSet.h"
//
//int main()
//{
// lrf::bitset<1000> bs;
// bs.set(1);
// bs.set(10);
// bs.set(100);
//
// cout << bs.test(1) << endl;
// cout << bs.test(10) << endl;
// cout << bs.test(100) << endl;
// cout << bs.test(999) << endl<<endl;
//
// bs.set(999);
// bs.reset(10);
//
// cout << bs.test(1) << endl;
// cout << bs.test(10) << endl;
// cout << bs.test(100) << endl;
// cout << bs.test(999) << endl << endl;
//
//
// lrf::bitset<-1> bs1;
// //bit::bitset<0xffffffff> bs2;
//
//
// return 0;
//}
//只出现一次
int main()
{
int a[] = { 1,2,3,3,4,4,4,4,4,2,3,6,3,1,5,5,8,9};
lrf::twobitset<10> tbs;
for (auto e : a)
{
tbs.set(e);
}
for (auto e : a)
{
if (tbs.is_once(e))
{
cout << e << " ";
}
}
cout << endl;
}
//求两个大文件中元素交集
//int main()
//{
// int a1[] = { 1,2,3,3,4,4,4,4,4,2,3,6,3,1,5,5,8,9 };
// int a2[] = { 8,4,8,4,1,1,1,1 };
//
// lrf::bitset<10> bs1;
// lrf::bitset<10> bs2;
//
// // 去重
// for (auto e : a1)
// {
// bs1.set(e);
// }
//
// // 去重
// for (auto e : a2)
// {
// bs2.set(e);
// }
//
// for (int i = 0; i < 10; i++)
// {
// if (bs1.test(i) && bs2.test(i))
// {
// cout << i << " ";
// }
// }
// cout << endl;
//}