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

C++进阶(七)--STL--bitset(位图)的介绍与基本功能模拟实现

在这里插入图片描述

文章目录

  • 引入
  • 1.位图的介绍
    • 1.1位图的概念
    • 1.2位图的应用
    • 1.3bitset的基本使用
      • bitset的定义方式
      • bitset成员函数的使用
  • 2.位图的基本模拟实现
    • 2.1基本结构
    • 2.2构造函数
    • 2.3set函数
    • 2.4reset
    • 2.5test
  • 3.位图考察题目
    • 3.1只出现⼀次的整数?
    • 3.2找到两个文件交集?
    • 3.3出现次数不超过2次的所有整数(出现1次和2次)?
  • 总结

引入

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

要判断一个数是否在某一堆数中,我们可能会想到如下方法:

  • 将这一堆数进行排序,然后通过二分查找的方法判断该数是否在这一堆数中。
  • 将这一堆数插入到unordered_set容器中,然后调用find函数判断该数是否在这一堆数中。
    单从方法上来看,这两种方法都是可以,而且效率也不错,第一种方法的时间复杂度是O(NlogN),第二种方法的时间复杂度是O(N)。

但问题是这里有40亿个数,若是我们要将这些数全部加载到内存当中,那么将会占用16G的空间,空间消耗是很大的。因此从空间消耗来看,上面这两种方法实际都是不可行的。

1.位图的介绍

实际在这个问题当中,我们只需要判断一个数在或是不在,即只有两种状态,那么我们可以用一个比特位来表示数据是否存在,如果比特位为1则表示存在,比特位为0则表示不存在。

在这里插入图片描述
无符号整数总共有232个,因此记录这些数字就需要232个比特位,也就是512M的内存空间,内存消耗大大减少。

1.1位图的概念

所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。

1.2位图的应用

常见位图的应用如下:

1. 快速查找某个数据是否在一个集合中。
2. 排序。
3. 求两个集合的交集、并集等。
4. 操作系统中磁盘块标记。
5. 内核中信号标志位(信号屏蔽字和未决信号集)。

1.3bitset的基本使用

bitset的定义方式

方式一: 构造一个16位的位图,所有位都初始化为0。

bitset<16> bs1; //0000000000000000

方式二: 构造一个16位的位图,根据所给值初始化位图的前n位。

bitset<16> bs2(0xfa5); //0000111110100101

方式三: 构造一个16位的位图,根据字符串中的0/1序列初始化位图的前n位。

bitset<16> bs3(string("10111001")); //0000000010111001

bitset成员函数的使用

bitset中常用的成员函数如下:

成员函数功能
set设置指定位或所有位
reset清空指定位或所有位
flip反转指定位或所有位
test获取指定位的状态
count获取被设置位的个数
size获取可以容纳的位的个数
any如果有任何一个位被设置则返回true
none如果没有位被设置则返回true
all如果所有位都被设置则返回true

具体用法可以用的时候再查询文档 bitset使用文档

2.位图的基本模拟实现

2.1基本结构

template<size_t N>
class bitset
{
public:// 构造函数bitset();// x映射的位标记成1void set(size_t x);// x映射的位标记成0void reset(size_t x);// x映射的位是1返回真,0返回假bool test(size_t x);
private:vector<int> _bs;
};

2.2构造函数

在构造位图时,我们需要根据所给位数N,创建一个N位的位图,并且将该位图中的所有位都初始化为0。

一个整型有32个比特位,因此N个位的位图就需要用到N/32个整型,但是实际我们所需的整型个数是N/32+1,因为所给非类型模板参数N的值可能并不是32的整数倍。

例如,当N为40时,我们需要用到两个整型,即40/32+1=2。

在这里插入图片描述

bitset()
{// 扩容,不管能否整除都多开一个空间_bs.resize(N / 32 + 1);
}

2.3set函数

设置位图中指定的位的方法如下:

计算出该位位于第 i 个整数的第 j 个比特位。
将1左移 j 位后与第 i 个整数进行或运算即可。
在这里插入图片描述

// x映射的位标记成1
void set(size_t x)
{size_t i = x / 32;size_t j = x % 32;_bs[i] |= (1 << j);
}

2.4reset

清空位图中指定的位的方法如下:

计算出该位位于第 i 个整数的第 j 个比特位。
将1左移 j 位再整体反转后与第 i 个整数进行与运算即可。
在这里插入图片描述

// x映射的位标记成0
void reset(size_t x)
{size_t i = x / 32;size_t j = x % 32;_bs[i] &= (~(1 << j));
}

2.5test

获取位图中指定的位的状态的方法如下:

计算出该位位于第 i 个整数的第 j 个比特位。
将1左移 j 位后与第 i 个整数进行与运算得出结果。
若结果非0,则该位被设置,否则该位未被设置。

在这里插入图片描述

// x映射的位是1返回真,0返回假
bool test(size_t x)
{size_t i = x / 32;size_t j = x % 32;return _bs[i] & (1 << j);
}

3.位图考察题目

  • 给定100亿个整数,设计算法找到只出现⼀次的整数?
    虽然是100亿个数,但是还是按范围开空间,所以还是开2^32个位,跟前面的题目是⼀样的。
  • 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
    把数据读出来,分别放到两个位图,依次遍历,同时在两个位图的值就是交集
  • ⼀个文件有100亿个整数,1G内存,设计算法找到出现次数不超过2次的所有整数 ?

根据上面的题意,我们需要通过位图实现一个能表示出现0次,1次,2次,多次的位图,因此可以实现一个两个位图成员的类。

namespace twobt
{template<size_t N>class twobitset{public:void set(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2) // 00->01{_bs2.set(x);}else if (!bit1 && bit2) // 01->10{_bs1.set(x);_bs2.reset(x);}else if (bit1 && !bit2) // 10->11{_bs1.set(x);_bs2.set(x);}}// 返回0 出现0次数// 返回1 出现1次数// 返回2 出现2次数// 返回3 出现2次及以上int get_count(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2){return 0;}else if (!bit1 && bit2){return 1;}else if (bit1 && !bit2){return 2;}else{return 3;}}private:bitset<N> _bs1;bitset<N> _bs2;};
}

3.1只出现⼀次的整数?

代码演示:

void test_twobitset1()
{lin::twobitset<100> tbs;int a[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6,6,6,6,7,9 };for (auto e : a){tbs.set(e);}// 只出现一次的整数for (size_t i = 0; i < 100; ++i){if (tbs.get_count(i) == 1){cout << i << endl;}}
}

3.2找到两个文件交集?

代码演示

void test_bitset()
{int a1[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6 };int a2[] = { 5,3,5,99,6,99,33,66 };bitset<100> bs1;bitset<100> bs2;for (auto e : a1){bs1.set(e);}for (auto e : a2){bs2.set(e);}// 两个文件的交集for (size_t i = 0; i < 100; i++){// 第i的位置都是1就是交集if (bs1.test(i) && bs2.test(i)){cout << i << endl;}}
}

3.3出现次数不超过2次的所有整数(出现1次和2次)?

代码演示

void test_twobitset2()
{lin::twobitset<100> tbs;int a[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6,6,6,6,7,9 };for (auto e : a){tbs.set(e);}// 出现次数不超过2次的所有整数for (size_t i = 0; i < 100; ++i){//cout << i << "->" << tbs.get_count(i) << endl;if (tbs.get_count(i) == 1 || tbs.get_count(i) == 2){cout << i << endl;}}
}

总结

位图的优缺点:
优点:增删查改快,节省空间
缺点:只适用于整形


本篇博客到此结束,欢迎各位评论区留言~

相关文章:

C++进阶(七)--STL--bitset(位图)的介绍与基本功能模拟实现

文章目录 引入1.位图的介绍1.1位图的概念1.2位图的应用1.3bitset的基本使用bitset的定义方式bitset成员函数的使用 2.位图的基本模拟实现2.1基本结构2.2构造函数2.3set函数2.4reset2.5test 3.位图考察题目3.1只出现⼀次的整数&#xff1f;3.2找到两个文件交集&#xff1f;3.3出…...

清北deepseek8本手册

“清北手册”通常是“清华大学和北京大学推出的DeepSeek手册”的简写。近期&#xff0c;随着AI技术的迅速发展&#xff0c;清北两高校陆续发布多本自家的DeepSeek学习手册&#xff0c;助力普通人学习进阶。 清华大学的DeepSeek手册已推出5册&#xff0c;内容丰富全面&#xff0…...

如何将Promise.then中的值直接return出来

Promise 如何返回值&#xff0c;而不是返回 Promise 对象。实际开发中使用封装好的异步请求函数&#xff0c;为什么调用该函数返回的值一直都是 undefined。 一、需求 定义一个 foo 函数&#xff0c;在里面执行异步操作&#xff0c;然后取得 Promise.then 中的值并 return 出来…...

利用golang embed特性嵌入前端资源问题解决

embed嵌入前端资源&#xff0c;配置前端路由的代码如下 func StartHttpService(port string, assetsFs embed.FS) error {//r : gin.Default()gin.SetMode(gin.ReleaseMode)r : gin.New()r.Use(CORSMiddleware())// 静态文件服务dist, err : fs.Sub(assetsFs, "assets/di…...

SPI驱动(二) -- SPI驱动程序模型

文章目录 参考资料&#xff1a;一、SPI驱动重要数据结构1.1 SPI控制器数据结构1.2 SPI设备数据结构1.3 SPI驱动数据结构 二、SPI 驱动框架2.1 SPI控制器驱动程序2.2 SPI设备驱动程序 三、总结 参考资料&#xff1a; 内核头文件&#xff1a;include\linux\spi\spi.h 一、SPI驱…...

【无标题】FrmImport

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;四、项目展示五、资源链接 前言 我能抽象出整个世界&#xff0c;但是我不能抽象你。 想让你成为私有常量&#xff0c;这样外部函数就无法访问你。 又想让你成为全局常量&#xff0c;这样在我的…...

深入浅出 Go 语言:协程(Goroutine)详解

深入浅出 Go 语言&#xff1a;协程(Goroutine)详解 引言 Go 语言的协程&#xff08;goroutine&#xff09;是其并发模型的核心特性之一。协程允许你轻松地编写并发代码&#xff0c;而不需要复杂的线程管理和锁机制。通过协程&#xff0c;你可以同时执行多个任务&#xff0c;并…...

vLLM代码推理Qwen2-VL多模态

由于近期代码微调以及测试都是在远程服务器上&#xff0c;因此LLamafactory-cli webui 以及vLLM的ui均无法使用&#xff0c;因此不断寻求解决方案&#xff0c;我提供一个解决方案&#xff0c;LLamafactory微调完成的模型需要合并为一个完整模型后再使用vLLM进行代码推理测试微调…...

DNS云解析有什么独特之处?

在数字化浪潮中&#xff0c;每一次网页点击、视频加载或在线交易背后&#xff0c;都依赖着域名系统&#xff08;DNS&#xff09;的高效运转。传统DNS架构的局限性&#xff08;如单点故障、延迟高、安全脆弱&#xff09;在云计算时代被彻底颠覆&#xff0c;DNS云解析作为新一代解…...

视频流畅播放相关因素

视频播放的流畅度是一个综合性问题&#xff0c;涉及从视频文件本身到硬件性能、网络环境、软件优化等多个环节。以下是影响流畅度的关键因素及优化建议&#xff1a; 一、视频文件本身 1. 分辨率与帧率 1.问题&#xff1a;高分辨率&#xff08;如4K&#xff09;或高帧率&#…...

Python实现一个类似MybatisPlus的简易SQL注解

文章目录 前言实现思路定义一个类然后开始手撸这个微型框架根据字符串获取到所定义的DTO类构建返回结果装饰器解析字符串&#xff0c;获得变量SQL字符串拼接 使用装饰器 前言 在实际开发中&#xff0c;根据业务拼接SQL所需要考虑的内容太多了。于是&#xff0c;有没有一种办法…...

linux一些使用技巧

linux一些使用技巧 文件名称和路径的提取切换用户执行当前脚本一行演示单引号与双引号的使用curl命令仅输出响应头信息,不输出body体文件名称和路径的提取 文件路径为 /tmp/tkgup/test.sh 方式获取文件名获取文件路径获取文件全路径方式一basename ${file}dirname ${file}real…...

小模型和小数据可以实现AGI吗

小模型和小数据很难实现真正的 通用人工智能&#xff08;AGI, Artificial General Intelligence&#xff09;&#xff0c;但在特定任务或受限环境下&#xff0c;可以通过高效的算法和优化方法实现“近似 AGI” 的能力。 1. 为什么小模型小数据难以实现 AGI&#xff1f; AGI 需…...

io学习----->文件io

思维导图&#xff1a; 一.文件io的概念 文件IO&#xff1a;指程序和文件系统之间的数据交互 特点&#xff1a; 1.不存在缓冲区&#xff0c;访问速度慢 2.不可以移植&#xff0c;依赖于操作系统 3.可以访问不同的文件类型(软连接&#xff0c;块设备等) 4.文件IO属于系统调…...

kubernetes介绍

文章目录 kubernetes概述kubernetes组件kubernetes概念 kubernetes概述 kubernetes&#xff0c;是一个全新的基于容器技术的分布式架构领先方案&#xff0c;是Google开源的的容器编排工具。 ​ kubernetes的本质是一组服务器集群&#xff0c;它可以在集群的每个节点上运行特定…...

如何高效准备PostgreSQL认证考试?

高效准备 PostgreSQL 中级认证考试&#xff0c;可从知识储备、技能提升、模拟考试等方面入手&#xff0c;以下是具体建议&#xff1a; 深入学习理论知识 系统学习核心知识&#xff1a;依据考试大纲&#xff0c;对 PostgreSQL 的体系结构、数据类型、SQL 语言、事务处理、存储过…...

如何使用Briefing打造私有视频会议系统结合内网穿透异地远程连接

文章目录 前言1.关于briefing2.本地部署briefing3.使用briefing4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定briefing公网地址 前言 在这个‘云’字当道的时代&#xff0c;远程办公、异地恋已经成了生活常态。视频聊天自然也就成了日常操作。但一不小心&#xff0c;…...

XHR请求解密:抓取动态生成数据的方法

在如今动态页面大行其道的时代&#xff0c;传统的静态页面爬虫已无法满足数据采集需求。尤其是在目标网站通过XHR&#xff08;XMLHttpRequest&#xff09;动态加载数据的情况下&#xff0c;如何精准解密XHR请求、捕获动态生成的数据成为关键技术难题。本文将深入剖析XHR请求解密…...

坐标变换介绍与机器人九点标定的原理

【备注】本文的C#代码在下面链接中可以下载:Opencv的C#九点标定代码资源-CSDN文库 https://download.csdn.net/download/qq_34047402/90452336 一、坐标变换的介绍 1.绕原点旋转的坐标变换 一个点(x,y)绕原点旋转u度,其旋转后的坐标(x1,y1)如何计算? 2.绕任意点的坐标变…...

串口调试助手Alien v5.198新版发布

v5.198 更改点: 1.增加USB打印机支持 2.支持特殊波特率/自定义波特率 3.支持窗口透明调整 4.支持接收框文本左/中/右对齐,粗体字,自动换行 5.支持接收时间戳 6.HEX接收自动换行 7.支持文本颜色主题 8.支持文本字体修改 9.增加菜单/增状态栏显示当前接口 下载 alien_v5.198.7z …...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...