【C++】位图的概念

news2025/1/18 17:16:56

文章目录

  • 位图的引入
  • 什么是位图
  • 位图的应用
  • bitset的使用
    • 定义方式
    • 成员函数
    • bitset的运算符重载
      • >> 及 << 运算符
    • 赋值,关系,复合赋值,单目运算符
    • []重载

位图的引入

无序的40亿个不重复的无符号整数,给一个无符号整数,如何判断一个数是否在这40亿个数中【腾讯面试题】

方法1:遍历, 时间复杂度O(N)

方法2:排序—O(N*logN) + 二分查找----O(logN)

方法3:可以将所有数放到unordered_set中,然后调用find函数查找

上述的方法存在的问题:

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

方法4:利用位图解决

无符号整数总共有2^32个,因此记录这些数字就需要2^32个比特位,仅仅需要512M的内存空间,内存消耗大大减少

问:40亿个整数需要占用多少空间

1G =1024*1024*1024 Byte = 10亿字节,刚才存放一个整形4个字节,32个比特位,需要16G的空间,现在用一个比特位存,只需要16/32 = 0.5G即可

注意我们需要开辟42亿9千多万个比特位,而不是40亿个比特位,因为要映射,要按照整数的最大范围去开,而不是按个数去开 开辟内存的最小单位->字节->用char/int都可以


如何正确开辟42亿9前多万个比特位呢?

共有两种方式: bitset: template<size_t N> class bitset;

bitset<0xffffffff> bs;//#define UINT_MAX      0xffffffff
bitset<-1> bs; //-1的补码是全1 0xffffffff,而非类型模板参数的N的参数是size_t类型

什么是位图

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

数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在

例子:

image-20220531233851748

位图的应用

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

bitset的使用

定义方式

bitset ---> template <size_t N> class bitset; 位图的大小在编译时是固定的(由其模板参数确定)

  • 构造一个N位的位图,所有位都初始化为0
  • 构造一个N位的位图,根据所给值初始化位图的前n位
  • 构造一个N位的位图,根据字符串中的0/1序列初始化位图的前n位
#include<bitset>
int main()
{
	//方式1:构造一个N位的位图,所有位都初始化为0
	bitset<16> bs1;//0000 0000 0000 0000

	//方式2:构造一个N位的位图,根据所给值初始化位图的前n位
	bitset<16> bs2(0xabc);//0011 1101 0101 0000

	//方式3:构造一个N位的位图,根据字符串中的0/1序列初始化位图的前n位
	bitset<16> bs3(string("10110001"));//1000 1101 0000 0000
	return 0;
}
image-20220602192428986

成员函数

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

使用实例:

#include<iostream>
#include<bitset>
int main()
{
	//从右到左算起, 最右边为第0位
	bitset<8> bs;//构造一个8位的位图,所有位都初始化为0
	bs.set(1);//设置第1位为1
	bs.set(5);//设置第5位为1
	cout << bs << endl; //00100010
	bs.flip();//反转bs的所有位
	cout << bs << endl;//11011101
	cout << "共有"<<bs.count()<<"位被设置成1" << endl;//共有6位被设置成1
	cout << bs.test(3) << endl;//输出第3位的状态 - 1
	bs.reset(1);//将第1位设置为0
	cout << bs << endl;//11011101
	bs.flip(7);//将第7位反转
	cout << bs << endl;//01011101
	cout << bs.size() << endl;//输出位图可以容纳的位的个数 ---8
	cout << bs.any() << endl;//判断是否有位被设置 ---1

	bs.reset();//清空所有位
	cout << bs << endl;//00000000
	bs.set();//将所有位设置为1
	cout << bs << endl;//11111111
	cout << bs.all() << endl;//判断是否所有位都设置 ----1
	return 0;
}

注意如何区分成员函数set,reset,flip是对所有位操作还是对某一个位操作呢?

  • 如果成员函数带了参数,就是对该指定的位操作
  • 如果没有指定,就是对所有位操作

bitset的运算符重载

>> 及 << 运算符

我们可以直接使用>><<运算符对biset容器对应的所有位进行输入输出操作

如果输入的位数比位图所能容纳的位数N多,只会从前向后截取N位

#include<bitset>
int main()
{
	bitset<8> bs;
	cin >> bs;//输入:10101
	cout << bs << endl;//00010101
	return 0;
}

赋值,关系,复合赋值,单目运算符

bitset容器对一些复合赋值运算符和单目运算符也进行了重载

  • 赋值运算符:=
  • 关系运算符:== !=
  • 复合赋值运算符:&= |= ^= <<= >>=
  • 单目运算符:~
#include<bitset>
int main()
{
	bitset<8> bs1(string("11111111"));
	bitset<8> bs2(string("01010101"));
	cout << bs1 << endl;//11111111
	bs1 >>= 1;
	cout << bs1 << endl;//01111111
	
	bs2 &= bs1;
	cout << bs2 << endl;//01010101
    
	return 0;
}

其次我们可以使用& | ^ 对位图进行操作

#include<bitset>
int main()
{
	bitset<8> bs1(string("10101111"));
	bitset<8> bs2(string("01101101"));

	cout << (bs1 | bs2) << endl;//11101111
	cout << (bs1 & bs2) << endl;//00101101
	cout << (bs1 ^ bs2) << endl;//11000010
	return 0;
}

[]重载

bitset容器中对[ ]运算符进行了重载,我们可以直接使用[ ]对指定位进行访问或修改

int main()
{
	bitset<8> bs(string("11001010"));
	cout << bs[0] << endl; //0
	bs[0] = 1;
	cout << bs << endl; //11001011
	return 0;
}

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

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

相关文章

记一次浏览器下载错误处理-失败网络错误

背景 最近在自己电脑上Chrome浏览器正常使用&#xff0c;但只要是下载软件&#xff0c;就会在下载几十秒后&#xff0c;自动停止&#xff0c;报失败-网络错误&#xff0c;导致文件都下载不成功&#xff0c;如下图。 猜测是更改了哪块的配置&#xff0c;导致一直中断&#xff0…

28岁,终于从字节退休了...

大厂一直是每个程序员都向往职业目标&#xff0c;大厂意味着薪资高、福利好、倍有面儿&#xff0c;而且发展空间也大。甚至有人调侃不想进大厂的程序员不是好程序员。 而在网上&#xff0c;也有各个网友分享自己在大厂的经历&#xff0c;在某平台还有一个近2600万浏览的话题&a…

JavaEE——了解Spring,容器,Ioc,DI相关概念

目录 一、Spring 是什么 二、什么是容器 三、什么是loC 1. 什么是 IoC 2. 传统程序开发和控制反转式程序开发 (1). 传统程序开发 (2). 控制反转式程序开发 (3). 对比 3. Spring的功能 4. 将对象存放到容器中的好处 四、DI概念说明 IoC和DI的联系和区别&#xff1f;…

算法 贪心1 || 455.分发饼干 376. 摆动序列 53. 最大子数组和

基础知识 什么是贪心&#xff1a;贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 但是贪心没有套路&#xff0c;做题的时候&#xff0c;只要想清楚 局部最优 是什么&#xff0c;如果推导出全局最优&#xff0c;其实就够了。 455.分发饼干 很容易想到&am…

Emlog底部显示当前在线人数

第一步&#xff1a;在模板文件里面创建“visitor.php”的文件吧下面代码入进去 code <?php//首先你要有读写文件的权限&#xff0c;首次访问肯不显示&#xff0c;正常情况刷新即可$online_log "slzxrs.dat"; //保存人数的文件到根目录,$timeout 30;//30秒内没…

计算机视觉__基本图像操作(显示、读取、保存)

计算机视觉__基本图像操作&#xff08;显示、读取、保存&#xff09; 本文目录&#xff1a; ✨ 一、前言 ✨ 二、图像显示&#xff08;使用OpenCV和Matplotlib显示图像&#xff09; &#xff08;1&#xff09;、使用OpenCV显示图像 &#xff08;2&#xff09;、使用Matplotl…

密集场景下的行人跟踪替代算法,头部跟踪算法 | CVPR 2021

一个不知名大学生&#xff0c;江湖人称菜狗 original author: Jacky LiEmail : 3435673055qq.com Time of completion&#xff1a;2023.4.8 Last edited: 2023.4.8 目录 摘要 主要内容 结果 这篇文章是CVPR 2021 的最新论文&#xff0c;文章的标题&#xff1a; 文章的主要内…

C#,数值计算的进化与发展——FORTRAN 77/80/95源程序 转C# 源程序的软件F2C#

1 F2C#FORTRAN 77/80/95源程序 转C# 源程序的软件 1.1 F2C#起源 全世界科学计算领域在超过40年的时间里累积了巨大数量的FORTRAN源程序&#xff08;尤其以FORTRAN77居多&#xff09;&#xff0c;实际上目前的许多大型科学软件还是以这些代码为基础的。众所周知的原因&#xf…

【youcans的深度学习 06】PyTorch入门教程:张量的基本操作

欢迎关注『youcans的深度学习』系列&#xff0c;持续更新中… 【youcans的深度学习 01】安装环境之 miniconda 【youcans的深度学习 02】PyTorch CPU版本安装与环境配置 【youcans的深度学习 03】PyTorch CPU版本安装与环境配置 【youcans的深度学习 04】PyTorch入门教程&#…

t-SNE进行分类可视化

0、引入 我们在论文中通常可以看到下图这样的可视化效果&#xff0c;这就是使用t-SNE降维方法进行的可视化&#xff0c;当然除了t-SNE还有其他的比如PCA等降维等方法&#xff0c;关于这些算法的原理有很多文章可以借阅&#xff0c;这里不展开阐释&#xff0c;重点讲讲如何进行…

window10 更新提示 0x80073712错误

解决方法&#xff1a; 1、可以尝试重新配置一下 Windows 更新服务状态&#xff1a; 2、Win S打开搜索&#xff0c;输入 CMD 找到 “命令提示符”&#xff0c; 3、右键以管理员身份打开&#xff0c;依次输入以下代码&#xff0c;并按回车执行。注&#xff1a;是一条一条的执行…

vue基础知识

1、特点 1.采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护。 2.声明式编码&#xff0c;让编码人员无需直接操作DOM&#xff0c;提高开发效率 命令式编码 3.使用虚拟DOM优秀的Diff 算法&#xff0c;尽量复用DOM节点。 2、hello vue vue的引入 就是写在引入c…

关键词词库制作-搜索词分析工具

关键词词库制作 关键词词库是一种帮助SEO和SEM优化的工具&#xff0c;它可以帮助您确定关键词的流行程度、竞争程度、搜索意图和其他相关信息等等。以下是一些关键词词库制作的方法&#xff1a; 收集关键词&#xff1a;首先需要收集相关的关键词&#xff0c;这可能涉及到您的业…

一文讲透产品经理如何用好ChatGPT

作者&#xff1a;京东零售 何雨航 “4.0版本的ChatGPT可以有效提升产品经理工作效率&#xff0c;但并无法替代产品经理的角色。” 一、引言 3月15日&#xff0c;OpenAI发布了最新的基于GPT-4的ChatGPT&#xff0c;关于其智能性的讨论热度在互联网上空前高涨。 我之前体验过3…

基于POSIX的消息队列的发送、接收demo的设计(linux)

本文介绍POSIX的消息队列的linux应用&#xff0c;新建两个进程&#xff08;一个发送进程、一个接收进程&#xff09;实现消息形式的数据传输。POSIX消息队列与SystemV消息队列存在相似的消息传输单位&#xff0c;但较SystemV消息队列更适合linux系统的使用。本文在ubuntu20.4上…

面试篇-深入理解 Java 中的 HashMap 实现原理

一、HashMap实现原理 HashMap 的实现主要包括两个部分&#xff1a;哈希函数和解决哈希冲突的方法。 1.哈希函数 当使用 put() 方法将键值对存储在 HashMap 中时&#xff0c;首先需要计算键的哈希值。HashMap 使用 hashCode() 方法获取键的哈希值&#xff0c;并将其转换为桶&…

Docker的常见命令

前言:使用Docker得学会的几个常见命令 常见命令前置学习: docker --help这个命令必须得会因为,很多命令是记不住的,得使用他们的官方help下面是一些实例 docker load --help常见命令集合: 一: docker images #查看全部镜像 docker rmi #删除某个镜像(例如:docker rmi redis…

Vue3——组件间通信的五种常用方式

Vue3组件间通信的五种常用方式 写在前面 本文采用<script setup>语法糖的编写方式&#xff0c;比options API更自由。 <script setup>语法糖详细内容看查看文档&#xff1a;setup语法糖官方文档 然后我们会讲以下五种常用的组件通信方式 propsemitv-modelrefs…

高速数字信号VS射频信号,到底哪个更难设计?

一博高速先生成员&#xff1a;黄刚熟悉高速先生的小伙伴们会知道&#xff0c;我们是以研究高速数字信号为主的团队&#xff0c;从不到1G到目前在研究的112G&#xff0c;高速先生就这样一直研究过来的&#xff0c;分享的案例也大多是以高速数字信号为主的案例。最近受到我们粉丝…

golang for range 令人抓狂的面试题

1.下面这段代码能否正常结束&#xff1f; func main() {v : []int{1, 2, 3}for i : range v {v append(v, i)} } 答案&#xff1a;正常结束。 可能我们会以为程序会陷入死循环。 但是我们要明白 for range 中的v其实就是复制了一份前面定义的v切片&#xff0c;不论前面定…