当前位置: 首页 > news >正文

C++----bitmap位图的使用

位图(Bitmap)是一种用二进制位(bit)来表示数据状态的存储结构,常用于节省内存、进行快速查找、去重或集合操作。

核心概念

位图的思想很简单:

用一个二进制位代表一个元素的“存在与否”。

  • 1 表示某个数存在;

  • 0 表示某个数不存在。

例如要存储 [1, 3, 5]

下标(表示数字)012345
位状态010101

这样我们只用了 6 位(二进制)就能表示 6 个数的存在性。


典型用途

  1. 大规模数据去重

    • 判断某个数是否出现过:O(1)

    • 内存比 unordered_setmap 小得多。

  2. 快速排序辅助

    • 只需扫描位图的每一位,即可得到排序结果(天然有序)。

  3. 布隆过滤器(Bloom Filter)底层实现

    • 位图配合多个哈希函数实现高效的“近似存在”判断。

  4. 权限管理 / 状态压缩

    • 用每一位代表某种状态或权限标记。

优点缺点
占用内存极小只能表示“是否存在”,不能存储实际值
查找速度极快只能用于整数或能映射成整数的值
可用于排序和去重数据范围过大时依然可能超内存(如 10¹² 级别)

面试题

1.给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。

第一个思路,遍历,虽然复杂度是O(N),但40亿不是小数目;第二种用红黑树,set解决,虽然他的插入和搜索很快,O(logN),但是建树很慢,约等于N*O(logN),也很大了;第三种排序+二分搜索,虽然搜索可以做到O(logN),但是排序最少也是O(N*logN),还是比较大的;同时,就算可以用上述的方式做到,40亿个整型数据,大概要占4000000000 个 int×4 字节=16000000000 字节÷1024÷1024÷1024≈14.9GB,试问一般的计算机内存大都是8GB,也有16GB的,但是总不能把空间都开给这个程序吧。所以这里就用到位图,可以缩小到八分之一,减小内存的消耗。

模拟实现,这里用到了位运算,大家可以自己动手理一理。通过对存放int的vector进行处理,set就是置1,reset置0,test检查是否存在X这个数字。这里还用到了非类型模板参数,在编译时可以确定参数的大小。注意resize中的数字正是为vector中存储的数据所开辟的个数,所以这里要注意,传入的N是比特位数,除以32就是int的数量。

template<size_t N>class bitmap{public:bitmap(){_bm.resize(N/32+1,0);}void set(int x){int i = x / 32;int j = x % 32;_bm[i] |= 1 << j;}void reset(int x){int i = x / 32;int j = x % 32;_bm[i] &= (~(1 << j));}bool test(int x){int i = x / 32;int j = x % 32;return _bm[i] & (1 << j);}private:vector<int> _bm;};

2.给定100亿个整数,设计算法找到只出现一次的整数?1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数。

这个题可以用两个位图来处理,我们先假设为每个值分配两个比特位,00代表不存在,10代表出现一次,01代表出现两次,11代表出现两次以上。那么是否要使用连续的两个比特位呢?不太好处理,那就用现成的位图:这个处理的是第一个问题,第二个问题可以扩展,请读者自行完成

	template<size_t N>class two_bitmap{public:void set(int x){//00一次也未出现if (!_bm1.test(x) && !_bm2.test(x)){_bm1.set(x);}//10出现了一次 设置成01else if (_bm1.test(x) && !_bm2.test(x)){_bm1.reset(x);_bm2.set(x);}//两次及两次以上else;}bool is_once(int x){return _bm1.test(x) && !_bm2.test(x);}private:bitmap<N> _bm1;bitmap<N> _bm2;};

3.给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?

要考虑到两个文件会中各自会有重复的文件,所以将两个文件考虑合并成一个文件,再用上面题2的处理方式是不行的。那么可以各自对应一个位图进行处理,数据存在的对应位置设置成1,不必理会是否重复。然后再对各自的位图进行检查:

	//假设a和b是两个不同的文件int a[] = { 1,2,3,4,5,6,7,1 };int b[] = { 2,4,6,8,3,1,0,8,9,4 };wzz::bitmap<10> b1;wzz::bitmap<10> b2;for (auto e : a){b1.set(e);}for (auto e : b){b2.set(e);}//利用set去重wzz::unorder_set<int> s1;for (auto e : a){if (b2.test(e))s1.insert(e);}cout << "交叉文件有:" << endl;for (auto e : s1){cout << e << " ";}
http://www.dtcms.com/a/456684.html

相关文章:

  • 单链表的应用02---算法中的暴力美学(第八讲)
  • 【RAG】优化query查询效果的几种处理
  • transformer详解(位置编码+attention+残差连接+全连接网络)
  • 已注册域名怎么做网站呢免费网站免费网站平台
  • 如何解决 pip install -r requirements.txt 约束文件 constraints.txt 仅允许固定版本(未锁定报错)问题
  • 【Camera】准备的一些Camera面试题——相机预览、拍照流程(经验尚欠,待补充)
  • CICD工具选型指南,GitLab cicd vs Arbess哪一款更好用?
  • 尉Lucene.Net 分词器选择指南:盘古分词 vs 结巴分词h
  • gitlab runner 安装
  • MySQL的OR条件查询不走索引及解决方案
  • 1688 店铺商品全量采集与智能分析:从接口调用到供应链数据挖掘
  • 淘宝商品详情采集方式,json数据返回
  • 【论文精度-1】 组合优化中的机器学习:方法论之旅(Yoshua Bengio, 2021)
  • 南京维露斯网站建设微信营销软件app
  • 从帧边界识别到数据编码:嵌入式通信协议与数据序列化方案深度对比
  • Quick SwiftObjective-C测试框架入门教程
  • GRM tools三大插件使用教程
  • C62-结构体的指针
  • 腾讯云 建网站企业网站seo公司
  • Java-143 深入浅出 MongoDB NoSQL:MongoDB、Redis、HBase、Neo4j应用场景与对比
  • 线程1——javaEE 附面题
  • 吴恩达机器学习课程(PyTorch适配)学习笔记:1.4 模型评估与问题解决
  • 后端_基于注解实现的请求限流
  • 从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 10--基础知识 6--元素等待方式和内联框架
  • 织梦网站如何做seo重庆市城市建设档案馆官方网站
  • 一文详解Go语言字符串
  • 通用:MySQL-LBCC并发锁机制
  • Elasticsearch:使用推理端点及语义搜索演示
  • 基于websocket的多用户网页五子棋(九)
  • Async++ 源码分析13--parallel_reduce.h