当前位置:网站首页>位图的详细介绍及模拟实现
位图的详细介绍及模拟实现
2022-06-29 17:38:00 【月半木斤】
目录
位图其实也是应用哈希思想的一种对数据进行快速查找的方法。位图将每个比特位的两种状态来表示数据的存在与否,0表示数据不存在1表示数据存在。实际应用中一般用来在特别大的数据量中查找元素是否存在。
1.位图的简单应用
我们先来看位图映射少量的元素:可以看到在一个数组中有1到22中个别元素如果如果我们每次查找数组中1~22中一个元素是否存在我们每次都需要遍历一遍数组那么是十分慢的,所以我们可以用位图的方式也就是用22个比特位来代表这22个数字的存在状态。那么我们每次判断一个数据是否存在于数组中就可以到位图中去查找。

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

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

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

3.2位图的使用:
- 位图中常见的用法:


- 可以看到这里最低位的位图中的元素在转化为字符串的时候被当作最低位的字符串

4. 位图的应用
4.1. 快速查找某个数据是否在一个集合中
- 我们上面查找数据就是应用位图来实现数的查找
4.2. 排序
- 在上面对于数据查找的过程中因为位图是按照顺序来进行标记数据的,那么在标记的过程中我们其实也就完成了对数据的排序过程。只要在位图中依次将置为1的位读出,那么就是集合中数据的次序。
4.3. 求两个集合的交集、并集等
- 交集:至于交集就更加容易实现了,我们只要将两个位图的每一位进行按位与操作那么得到的新的位图中标记的数据就是原本两个集合的交集。
- 并集:对两个位图进行按位或操作得到的新的位图就是原本两个集合的并集。
4.4. 操作系统中磁盘块标记
(1条消息) Linux下文件系统_月半木斤的博客-CSDN博客
https://blog.csdn.net/weixin_45897952/article/details/123262685?spm=1001.2014.3001.5501

5.位图的模拟实现
#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;
}测试结果:

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

边栏推荐
- 剑桥大学教授:经常吃早餐害处多,很危险 - 知乎
- What role does the supply chain management system play in the supply chain scenario?
- Online sql to CSV tool
- Kubernetes部署Dashboard(WEB UI管理界面)
- R language uses user-defined functions to write deep learning linear activation functions and visualize linear activation functions
- 基于STM32F103ZET6库函数PWM输出实验
- 自定义HandlerInterceptor拦截器实现用户鉴权
- mysql.sock的概念是什么
- OpenFeign使用步骤 轮询策略与权重 log4j使用 openFeign拦截器的配置
- 腾讯云发布自动化交付和运维产品Orbit,推动企业应用全面云原生化
猜你喜欢

How to solve the 2003 error of MySQL in Linux

如何使用B/S开发工具DevExtreme的图表控件 - 自定义轴位置?

Online text digit recognition list summation tool

剖析下零拷贝机制的实现原理,适用场景和代码实现

MySQL触发器如何创建与删除

Mysql中锁的使用场景是什么

selenium 文件上传方法

Walk with love, educate and run poor families, and promote public welfare undertakings

Does MySQL support foreign keys

SRM供应商协同管理系统功能介绍
随机推荐
What is a SCM system? What are the advantages of a supply chain management system?
Issue 42: is it necessary for MySQL to have multiple column partitions
PancakeSwap技术:夹子机器人系统开发原理
Kali installation tutorial 2020
What role does the supply chain management system play in the supply chain scenario?
Mysql中锁的使用场景是什么
The soft youth under the blessing of devcloud makes education "smart" in the cloud
About Kali using xshell connection
Go语言多方式并发实现龟兔赛跑
2022 software evaluator examination outline
The aggregate function in the epidisplay package of R language divides numerical variables into different subsets based on factor variables, and calculates the summary statistics and aggregate data. W
Openfeign use step polling strategy and weight log4j configuration of openfeign interceptor
Bottom level internal skill cultivation
What is the MySQL query view command
2022 spring summer collection koreano essential reshapes the vitality of fashion
What is the function of MySQL cursors
R语言ggplot2可视化:使用patchwork包(直接使用加号+)将两个ggplot2可视化结果横向组合、接着再和第三个图像横向组合起来(三幅图各占比例为50%、25%、25%)
在线SQL转CSV工具
R language ggplot2 visualization: use the patchwork package (directly use the plus sign +) to horizontally combine the two ggplot2 visualization results, and then horizontally combine them with the th
填充每个节点的下一个右侧节点指针[利用好每个点->尽可能降低时空复杂度]


