目录
位图其实也是应用哈希思想的一种对数据进行快速查找的方法。位图将每个比特位的两种状态来表示数据的存在与否,0表示数据不存在1表示数据存在。实际应用中一般用来在特别大的数据量中查找元素是否存在。
我们先来看位图映射少量的元素:可以看到在一个数组中有1到22中个别元素如果如果我们每次查找数组中1~22中一个元素是否存在我们每次都需要遍历一遍数组那么是十分慢的,所以我们可以用位图的方式也就是用22个比特位来代表这22个数字的存在状态。那么我们每次判断一个数据是否存在于数组中就可以到位图中去查找。

在实际的生活中我们要处理的数据是往往是十分巨大的,例如我们要处理40亿的数据。要求查找40亿的数据中某个元素是否存在那么我们就可以用位图的方式来表示。
首先我们来计算一下不用位图的方式来查询四十亿数据。那么我们首先大概计算一下40亿数据大概是占用多少内存。

我们可以看到40亿数据有大约16个G我们采用内部排序(这里查找的本质就是排序,就是在查找的过程中对每个元素进行排序对比)是很难进行的因为要一次性将16G的数据全部都加载到内存中才可以一一进行查找比对。但是实际中我们的内存可能只有8G或者16G要是将这16G的数据全部都加载到内存中肯定是不合理的。那么就需要外部排序,但是外部排序也需要对文件进行合并排序,排序复杂而且耗费时间。那么我们就可以用位图的方式来轻松解决。

我们可以看到用位图的方式我们只需要申请512M数据就可以实现40亿的数据的查找。
可以看到STL中的位图是一个特化的模板直接给出一个无符号的N来表示位图的比特个数。




https://blog.csdn.net/weixin_45897952/article/details/123262685?spm=1001.2014.3001.5501
- #pragma once
- #include<iostream>
- #include<vector>
- #include<assert.h>
- using namespace std;
- namespace wbx
- {
- template<size_t N>
- class bitset
- {
- public:
- bitset()
- :_con(N/8+1),_count(0)
- {}
- bitset& set(size_t pos, bool val = true)
- {
- if (pos >= N)
- {
- assert(true);
- }
- if (val)
- {
- _con[pos / 8] |= (1 << (pos % 8));
- _count++;
- }
- else
- {
- reset(pos);
- }
- return *this;
- }
-
- bitset& reset(size_t pos)
- {
- _con[pos / 8] &= (~(1 << (pos % 8)));//将其置0
- _count--;
- return *this;
- }
-
- size_t count()
- {
- //这里也可以用我们实现给好的每个数字对应的位图中数字的个数来计算count的值
- //int bitCnttable[256] = {
- // 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
- // 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
- // 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
- // 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
- // 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
- // 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
- // 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
- // 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
- // 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
- // 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
- // 6, 7, 6, 7, 7, 8 };
- //_count = 0;
- //for (int i = 0; i <_con.size(); i++)
- //{
- // _count += bitCnttable[_con[i]];
- //}
-
- return _count;
- }
- size_t size()
- {
- return N;
- }
-
- bool test(size_t pos)
- {
- int temp = _con[pos / 8] & (1 << (pos % 8));
- return bool(temp > 0 ? true : false);
- }
- //?????????????没写出来
- unsigned char& operator[](size_t pos)
- {//不知道怎样返回一个位置的引用
- return _con[pos / 8];
- }
- string to_string()const
- {
- string ret;
- bool flag = false;
- for (int i = 0; i < _con.size(); i++)
- {
- if (i == _con.size())
- {
- flag = true;
- }
- ret += char_tostring(_con[i], flag);
- }
- return ret;
- }
- unsigned long to_ulong()const
- {
- unsigned long ret=0;
- string temp = to_string();
- int base = 0;
- for (int i = temp.size() - 1; i >= 0; i--)
- {
- ret += (temp[i] - '0')*Nsquare(base);
- base++;
- }
- return ret;
- }
- private:
- long Nsquare(int N)const
- {
- long ret = 1;
- for (int i = 0; i < N; i++)
- {
- ret *= 2;
- }
- return ret;
- }
- string char_tostring(unsigned char num,bool flag)const
- //flag用于表示当前是否是最后一位
- {
- string rets;
- while (num)
- {
- unsigned long temp = num % 2;
- num /= 2;
- rets.push_back((char)(temp + '0'));
- }
- if (!flag)
- {
- while (rets.size() < 8)
- {
- rets.push_back('0');
- }
- }
- reverse(rets.begin(), rets.end());
- return rets;
- }
- vector<unsigned char> _con;
- size_t _count;
- };
- }
-
-
-
- int main()
- {
- wbx::bitset<23> b;//这里我们因为要表示0-22之间的元素存在情况所以我们要构造23个空间因为还包括0
- int array[] = { 1, 3, 7, 4, 16, 12, 13, 19, 22, 18 };
- for (int e : array)
- {
- b.set(e);//将数组中每一个数据都在位图中置为1
- }
- if (b.test(1))
- {
- cout << "1 is in bitset" << endl;
- }
- else
- {
- cout << "1 is not in bitset" << endl;
- }
- b.reset(1);//将1位置置为0
- if (b.test(1))
- {
- cout << "1 is in bitset" << endl;
- }
- else
- {
- cout << "1 is not in bitset" << endl;
- }
- cout << b.size() << endl;//位图的个数
- cout << b.count() << endl;//位图中被置为1的个数
- if (b.test(4))
- {
- cout << "4 位置在位图中被置为1" << endl;
- }
- else
- {
- cout << "4 位置在位图中没有被置为1" << endl;
- }
- if (b.test(10))
- {
- cout << "10 位置在位图中被置为1" << endl;
- }
- else
- {
- cout << "10 位置在位图中没有被置为1" << endl;
- }
- cout << b.to_string() << endl;//将位图中每位的设置情况转化为字符串
- cout << b.to_ulong() << endl;//将位图中每位的设置情况转化为无符号long型
- return 0;
- }
测试结果:

看到这里如果觉得有用不如点个赞再走吧!!!
