【高级程序设计语言C++】位图

news2025/2/27 3:58:41

  • 1. 位图
    • 1.1. 位图的模型图
    • 1.2. 判断一个数是否存在
  • 2. 位图的实现
    • 2.1. 位图的基础模型
    • 2.2. 位图开辟空间的大小
    • 2.3. 位图的插入
    • 2.4. 位图的删除
    • 2.5. 位图的查询
  • 3. 位图的应用
  • 4. 哈希切分
  • 5. 位图的优缺点

1. 位图

C++中的位图(Bitset)是一种用于存储和操作二进制位的数据结构。它可以看作是一个固定大小的数组,每个元素只能是0或1,对应于二进制位的值。

使用位图可以高效地存储和操作大量的布尔值,因为每个元素只占用一个位,而不是一个字节。这样可以节省内存,并且可以进行位运算操作,例如与、或、异或等。

C++标准库提供了std::bitset模板类来实现位图。它的大小在编译时确定,并且可以通过模板参数指定位图的大小。std::bitset提供了一系列成员函数和操作符,用于对位图进行设置、获取、修改和比较等操作。

1.1. 位图的模型图

位图说白了就是一个数组,其中数组元素的大小是一个比特位。

img

1.2. 判断一个数是否存在

有这样的一道题:

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

面对这样的题,首先是数据量太大,40亿,依次遍历的话是O(n),内存是不够的。那么就考虑用红黑树或者哈希桶这样的数据结构去存储,然后再去遍历,那也还是面临同样的问题,内存不够。40亿个整数也就是40亿个字节大小 = 16G

但是注意题目中要求的是判断一个数是否在这40亿个数当中?

如果仅仅是判断在不在,就只需要一个比特位就可以判断。那么就可以针对这40亿个数,针对数值的大小来开辟空间,然后标记数字是否存在。

img

用一个哈希函数,比如是直接定址法确定每个数的位置,然后把该位置标记成1或者0,其中1代表存在,0代表不存在。

那么说回内存的问题,40亿个int = 16 G, 那么40亿个bit等于多少呢? 一个字节(int) = 8 个比特位(bit),所以上面开辟的空间最多也就是0.5G,对于计算机来说是可以接受的,并且非常的快。而这种做法的数据结构就是位图。

2. 位图的实现

针对上面的问题,我们需要做的就是开辟一个数组,针对这个数组的每一个bit操作。

假设我们有这样一个char数组如下,

img

我们所需要思考的就是

  1. X这个数映射的值,在第几个char呢?
  2. X这个数映射的值确定了第几个char,那么在char的第几个位呢?

比如10这个数

  1. 想要求出10映射在第几个char,只需要 10 / 8即可, 所以第一个问题解决的办法是 : X / 8
  2. 求映射在char的第几个位,只需要10 % 8 即可,第二个问题解决的办法就是:X % 8

2.1. 位图的基础模型

img

2.2. 位图开辟空间的大小

根据上面的模型,我们知道N是指的多少个bit,那么一个char = 8bit,所以构造函数开辟空间大小就应该为:N / 8 + 1个char,其中每个char是0

BitSet()
{
    _bits.resize(N / 8 + 1, 0);
}

这里为什么要+1呢? 是因为有些数是除不完整的,例如18 / 8,你总不能直接开2个char吧,那剩下的两个bit怎么办?

2.3. 位图的插入

位图的插入首先通过 i = X / 8确定了在第几个char,但是怎么让这个char的 j = X % 8的位置成标记1呢,其他位不变?

这里可以用到位运算,假设 j = X % 8,先让1左移 j 位,然后与_bits[i]相或即可。

void set(size_t x)
{
    size_t i = x / 8;
    size_t j = x % 8;

    _bit[i] |= (1 << j);
}

如下图所示:

img

2.4. 位图的删除

位图的删除,总的来说就是,其他位不变,第j位变为0.

我们可以用一个数跟_bit[i]相与即可,怎么样能拿到这个数呢?

可以取上面的1左移j位的数取反,就可以得到这个数。

void reset(size_t x)
{
    size_t i = x / 8;
    size_t j = x % 8;

    _bit[i] &= (~(1 << j));
}

相关的图就不画了,读者可以自行画一画。

2.5. 位图的查询

位图的查询只需要知道j位置的值是0还是1,是0就是不存在,是1就是存在。

bool test(size_t x)
{
    size_t i = x / 8;
    size_t j = x % 8;
    return _bit[i] & (1 << j);
}

这样写的意思是,只需要关心j位置是0还是1,如果是0,那么返回的结果就是0(false),如果是1,那么返回的结果就是非0(true)。

3. 位图的应用

上面的2.3 、2.4和2.5只是位图的常用接口,有兴趣的读者可以取c++官网去看完整的位图,在库里位图的名字是bitset。库里的bitset

  1. 给定100亿个整数,设计算法找到只出现一次的整数?

可以用两个位图来解决这个问题,题目只是要求找到只出现一次的数,那么用两个位图组合起来,就可以对一个数进行一个计数,分别1、2、3、4的计数,对应的就是00、01、10、11,如下图:

img

计数完成后,再用test接口查询次数是否为1即可。

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

采用上面问题1的方法,也是采用两个位图,分别存储这两个文件,然后再一个一个位对比即可。

  1. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

这个问题其实就是问题1的变形,也是采用两个位图存储数据的方式,然后依次查找出符合要求的整数即可。

4. 哈希切分

给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?

这题最好的办法就是切分,把这个file切分一个一个的小文件,然后去统计这些小文件中ip的次数,用map去统计次数,然后清空map,再统计下一个小文件。但是这样会有一个问题,那就是一个小文件并不代表的是一个ip的准确次数。有可能这个小文件存在一个ip5次,下一个小文件存在10次,但是要知道在统计下一个小文件的时候,map会清空,导致无法统计,那怎么办呢?

这时候最好使用哈希切分。用一个哈希函数把每个ip的哈希值求出来,然后利用这个哈希值,把和这个哈希值相等的ip都放进一个小文件中,这样统计的就是这个ip的次数。

如图所示:

img

但此时会有一个问题:

单个小文件超过了1G怎么办?

此时应该分两种情况分析:

  1. 小文件中ip都是重复的,map可以统计的下
  2. 小文件中ip都是不重复的,map统计不下

面对第一种情况,基本不用处理,因为map都可以统计的下。

第二种情况,就要用另一个哈希函数重新对小文件中的ip再次切分,再次统计。

5. 位图的优缺点

优点:

  1. 节省空间

缺点:

  1. 要求范围相对集中,范围要是分散,空间消耗有所上升
  2. 类型只能是整形

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/894100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows下问题定位

1、内存相关知识点&#xff1b; 1&#xff09;windows下32位进程&#xff0c;用户态为2G内存&#xff0c;内核态也为2G内存&#xff1b;却别于linux操作系统&#xff1b; 备注&#xff1a;可以通过命令行与管理员权限&#xff0c;启动3G的用户态空间&#xff0c;但是部…

【数学建模】-- 数学规划模型

概述&#xff1a; 什么是数学规划&#xff1f; 数学建模中的数学规划是指利用数学方法和技巧对问题进行数学建模&#xff0c;并通过数学规划模型求解最优解的过程。数学规划是一种数学优化方法&#xff0c;旨在找到使目标函数达到最大值或最小值的变量取值&#xff0c;同时满足…

免费内网穿透哪个好?

神卓互联是一种内网穿透技术&#xff0c;可以实现在外部网络访问公司内网的服务。通过建立一个加密的通道&#xff0c;神卓互联可以将内网的动态IP绑定技术&#xff0c;实现远程访问。 使用神卓互联进行内网穿透的步骤如下&#xff1a; 在公司内网中&#xff0c;安装并配置神卓…

Linux 进程间通信——有名管道和无名管道

一、管道的概念 当从一个进程连接数据流到另一个进程时&#xff0c;我们使用管道。通常把一个进程的输出通过管道连接到另一个进程的输入。 管道可以用来在两个进程之间传递数据&#xff0c;如&#xff1a; ps -ef | grep “bash”, 其中‘|’就是管道&#xff0c;其作用就是…

CH32V203 单片机 I2C 使用

CH32V203系列是基于32位RISC-V内核设计的工业级增强型低功耗通用微控制器&#xff0c;高性能&#xff0c;最高支持144MHz系统主频&#xff0c;低功耗&#xff0c;运行功耗低至45uA/MHz。CH32V203集成双路USB接口&#xff0c;支持USB Host主机及USB Device设备功能&#xff0c;具…

[NAS4]Tiny adversarial multi-objective one-shot neural architecture search

论文链接&#xff1a;https://arxiv.org/abs/2103.00363v1 代码链接&#xff1a; 摘要&#xff1a;移动设备中广泛使用的微小神经网络&#xff08;TNN&#xff09;容易受到对抗性攻击&#xff0c;对TNN鲁棒性的更先进研究需求也越来越大。 本文关注于如何在不损失模型精度的…

【win7Window】高仿Windows7系统窗体

特性&#xff1a; 任意拖拽到边界可以最大化、半屏放大双击边界可以水平、纵向最大化可以拖拽四边、四个顶点调整窗体尺寸可以最大化、还原、最小化、关闭支持双击标题栏最大化、还原支持双击左上角图标关闭窗体 win7Window源码 <template><div :class"$options…

JS的解析与Js2Py使用

JS的解析与Js2Py使用 JS的解析事件监听器搜索关键字请求关联JS文件 Js2PyJs2Py的简单使用安装Js2Py执行JavaScript代码调用JavaScript函数 Js2Py的应用示例创建JavaScript文件使用JavaScript JS的解析 在一个网站中&#xff0c;登录密码通常是会进行加密操作的&#xff0c;那么…

LeetCode--HOT100题(34)

目录 题目描述&#xff1a;94. 二叉树的中序遍历&#xff08;简单&#xff09;题目接口解题思路1代码解题思路2代码 PS: 题目描述&#xff1a;94. 二叉树的中序遍历&#xff08;简单&#xff09; 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 LeetCode做…

el-table根据容器大小自适应滚动条-修改滚动条样式

需求&#xff1a;父容器里有多个容器为上下级&#xff0c;之后浏览器在缩放的时候&#xff0c;上面容器高度改变了&#xff0c;所以el-table被挤压&#xff0c;如果el-table设置的是固定的高度&#xff0c;那么挤压后内容超出父容器&#xff0c;本文章就是解决这个问题 不自适…

拒绝无效内卷!新同事靠着这套大屏模板效率翻倍,搭上升职快车!

竞争是职场永恒的话题&#xff0c;太多人为了升职加薪卷生卷死&#xff0c;就拿我自己身边来说&#xff0c;这段时间我所在的小组有一个升职机会&#xff0c;好多老员工为了这个机会争得头破血流&#xff0c;一个在公司待了10年的老员工&#xff0c;直接天天加班到12点&#xf…

蓝牙耳机的发展

目录 1.蓝牙耳机的概念 2.蓝牙耳机的发展过程 3.蓝牙耳机的便利性 4.蓝牙耳机未来的发展趋势 1.蓝牙耳机的概念 蓝牙耳机是一种使用蓝牙无线技术连接到音频源设备&#xff08;如智能手机、平板电脑、电脑等&#xff09;的耳机。它们通过无线蓝牙信号接收音频数据&#xff0c…

MybatisPlus的使用

一. 关于注解的使用&#xff0c;官方地址&#xff1a; 注解 | MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/pages/223848/#tablename 1.关于TableName的使用 假设我们不加TableName("tbl_employee")的话&#xff0c;那么数据库中的表名和类名相同的话&…

Qt下拉菜单

1&#xff0c;QComboBox 2&#xff0c;setMenu()---设置下拉菜单 AI对话未来丨智能写作对话: setMenu()是QWidget类的一个成员函数&#xff0c;在Qt中用于将一个菜单作为一个控件的下拉菜单设置。具体来说&#xff0c;它会把相应的菜单对象与该控件关联&#xff0c;并在控件上…

Mysql8.0为什么取消了缓存查询的功能

首先我们介绍一下MySQL的缓存机制 【MySQL缓存机制】简单的说就是缓存sql文本及查询结果&#xff0c;如果运行完全相同的SQL&#xff0c;服务器直接从缓存中取到结果&#xff0c;而不需要再去解析和执行SQL。 但如果表中任何数据或是结构发生改变&#xff0c;包括INSERT、UPD…

问道管理:放量打拐什么意思?常见的放量打拐三种形态?

成交量一直是股票交易中比较重要的目标&#xff0c;那么&#xff0c;放量打拐是什么意思&#xff1f;常见的放量打拐三种形状是什么&#xff1f;下面问道管理为我们预备了相关内容&#xff0c;以供参阅。 放量打拐什么意思&#xff1f; 放量是指股票成交量与前几个交易日比较显…

隐私文件夹怎么加密?隐私文件夹加密方法

在个人电脑中&#xff0c;我们经常会将一些个人隐私存放在电脑文件夹中&#xff0c;这些文件夹都需要加密保护。那么&#xff0c;隐私文件夹该怎么加密呢&#xff1f;下面我们就来了解一下吧。 超级秘密文件夹 隐私数据存放在文件夹中&#xff0c;最怕的就是被其他人发现。而如…

迅镭激光中标全球集装箱行业龙头中集集团10家子公司集采项目!

迅镭激光中标喜报频传!继连续中标工程机械、钢构、船舶、电力电气、新能源等多个行业龙头企业后&#xff0c;近日再次中标全球集装箱行业龙头中集集团(CIMC)&#xff0c;这与迅镭激光坚持高端、注重技术引领、十五年的技术沉淀和口碑积累密不可分。 日前&#xff0c;中集集团20…

如何使用ChatGPT创作一个小说式的虚构的世界

世界构建也许是小说写作中最重要的一环&#xff0c;但也可能非常耗时。让ChatGPT加快这一过程吧。 写小说最棒的一点就是有机会从零开始创造一个新世界。你可以创造超凡脱俗的景观&#xff0c;赋予人物魔法。神话故事可以存在于你小说中的现实世界&#xff0c;而传统可以帮助你…