C++ bitset(位图)的介绍和使用

文章目录

  • 一、bitset的介绍
    • 1. 位图的引入
    • 2. 位图的概念
    • 3. 位图的应用场景
  • 二、bitset的使用
    • 1. 定义方式
    • 2. 成员函数
    • 3. 运算符重载


一、bitset的介绍

1. 位图的引入

面试题

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

  1. 遍历,时间复杂度O(N)
  2. 排序(O(NlogN)),利用二分查找: logN

单从方法上来说这两种方法都是可以的,但是从内存上来说,这里有40亿个整数,换算一下就相当于16G,也就是说要操作这些数据的话需要占用16G的内存,内存消耗是很大的,所以从内存上来看,这两种方法都是不合适的。
所以我们采用第三种方法来解决这个问题:

  1. 位图解决

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

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

2. 位图的概念

  1. 定义:位图是一种紧凑型数据结构,用于表示一个固定大小的集合或序列中的元素状态(存在或不存在)。它通常用于处理一组整数值或布尔值,例如集合操作、数据筛选和计数等应用场景。
  2. 工作原理:位图通过使用位数组来表示集合中的元素状态,每个元素对应一个位(bit),从而实现高效的空间和时间性能。位图通过一系列位数组(通常使用unsigned char或unsigned int类型的数组)来表示一组元素的状态。数组中的每一位(bit)表示集合中的一个元素的存在与否。
  3. 特点
    • 高效的空间利用率:位图在表示大范围的数据时非常紧凑,每个元素只需要一个位。
    • 快速的集合操作:位图支持高效的并集、交集和差集操作,这些操作可以通过位运算来实现。
    • 快速的存在检查:位图可以快速检查某个元素是否存在于集合中,通过索引直接访问位数组。
    • 固定大小:位图通常适用于固定大小的集合。如果要表示的集合范围不固定,可能需要额外的空间。
    • 不适合稀疏数据:位图在表示稀疏数据时可能浪费大量空间,因为空闲的元素仍然会占用位数组的空间。

3. 位图的应用场景

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

二、bitset的使用

1. 定义方式

bitset有三种定义方式。

  • 第一种:定义一个N个比特位的,初始值全为0的位图,这里的N是一个正整数,比如我们创建一个8个比特位的全为0的位图:
bitset<8> a;  //00000000

在这里插入图片描述

  • 第二种:构建一个位图,并根据所给的初始值,初始化位图的前几位。
bitset<8> a(9);  //0000 1001

在这里插入图片描述

  • 第三种:利用01字符串初始化位图的前n位
bitset<8> a(string("0111001"));  //00111001

在这里插入图片描述

2. 成员函数

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

成员函数功能
set设置指定位或所有位为1(即设置为“已设置”状态)
reset清空指定位或所有位,将其设为0(即设置为“未设置”状态)
flip反转指定位或所有位的状态。如果位是0,则变为1;如果位是1,则变为0
test获取指定位的状态。如果位是1,则返回true;如果位是0,则返回false
count获取被设置为1的位的个数(即“已设置”的位的数量)
size获取位图可以容纳的位的总数。这通常指的是位图数组的总大小(以位为单位)
any如果有任何一个位被设置为1(即至少有一个位是“已设置”状态),则返回true;否则返回false
none如果没有位被设置为1(即所有位都是“未设置”状态),则返回true;否则返回false
all如果所有位都被设置为1(即所有位都是“已设置”状态),则返回true;否则返回false

使用示例:

在这里插入图片描述

#include <iostream>
#include <bitset>
using namespace std;int main()
{bitset<8> bs;bs.set(2); //设置第2位bs.set(4); //设置第4位cout << bs << endl; //00010100bs.flip(); //反转所有位cout << bs << endl; //11101011cout << bs.count() << endl; //6cout << bs.test(3) << endl; //1bs.reset(0); //清空第0位cout << bs << endl; //11101010bs.flip(7); //反转第7位cout << bs << endl; //01101010cout << bs.size() << endl; //8cout << bs.any() << endl; //1bs.reset(); //清空所有位cout << bs.none() << endl; //1bs.set(); //设置所有位cout << bs.all() << endl; //1return 0;
}

3. 运算符重载

1. bitset中输入输出的使用

bitset中对>><<进行了重载,所以我们可以直接使用cincout对位图进行输入和输出

#include <iostream>
#include <bitset>
using namespace std;int main()
{bitset<8> bs;cin >> bs; //10110cout << bs << endl; //00010110return 0;
}

在这里插入图片描述
2. bitset中运算符的使用

bitset容器中,不仅基本的赋值运算符(=)和一些关系运算符(==!=)被重载,还对一些复合赋值运算符(&=|=^=<<=>>=)和单目运算符(~)进行了重载。这使得我们可以直接使用这些运算符来对bitset对象(即位图)进行各种操作,如位的赋值、比较、逻辑运算、位移以及取反等。

例如,以下代码展示了如何使用这些运算符:

#include <iostream>
#include <string>
#include <bitset>
using namespace std;int main() {bitset<8> bs1(string("10101010"));bitset<8> bs2(string("10101010"));// 使用复合赋值运算符右移bs1bs1 >>= 1;cout << bs1 << endl; // 输出: 01010101// 使用复合赋值运算符进行位或操作bs2 |= bs1;cout << bs2 << endl; // 输出: 11111111// 使用单目运算符取反// 注意:这里未直接展示,但可以通过 bs2 = ~bs2; 来实现return 0;
}

在这里插入图片描述

3. bitset中位运算符的使用

bitset容器还重载了三个位运算符(&|^),允许我们直接对两个bitset对象进行按位与、按位或、按位异或操作。

以下是示例代码:

#include <iostream>
#include <string>
#include <bitset>
using namespace std;int main() {bitset<8> bs1(string("10101010"));bitset<8> bs2(string("01010101"));// 使用位运算符cout << (bs1 & bs2) << endl; // 输出: 00000000cout << (bs1 | bs2) << endl; // 输出: 11111111cout << (bs1 ^ bs2) << endl; // 输出: 11111111(因为bs1和bs2在每个位上都是相反的)return 0;
}

在这里插入图片描述

4. bitset中[ ]运算符的使用

bitset容器还重载了[ ]运算符,允许我们直接通过索引来访问或修改bitset中指定位置的位。

以下是示例代码:

#include <iostream>
#include <string>
#include <bitset>
using namespace std;int main() {bitset<8> bs(string("00110101"));// 使用[ ]运算符访问和修改位cout << bs[0] << endl; // 输出: 1(因为索引从0开始,所以访问的是最右边的位)bs[0] = 0; // 修改最右边的位为0cout << bs << endl; // 输出: 00110100return 0;
}

在这里插入图片描述

通过这些示例,我们可以看到bitset容器提供了丰富的运算符支持,使得对位图的操作既方便又高效。

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

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

相关文章

2024年蓝牙网关市场热门产品选购宝典

在本文中&#xff0c;我们将探讨不同类型的蓝牙网关及其分类&#xff0c;并提供一份指南&#xff0c;帮助您筛选出最适合的物联网网关。 室内蓝牙网关 室内网关通常用于智能建筑解决方案&#xff0c;如智能家居、零售店、购物中心和办公室。 这些网关的覆盖范围较短&#xff…

人工智能代表——无人驾驶:萝卜快跑

人工智能如何改变我们的出行&#xff1a;以“萝卜快跑”无人驾驶为例 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的方式渗透并改变着我们的日常生活&#xff0c;其中出行方式的变革尤为显著。在众多AI驱动的出行创新中&#xff0c;“萝卜…

【hot100-java】【缺失的第一个正数】

R9-普通数组篇 class Solution {public int firstMissingPositive(int[] nums) {int nnums.length;for (int i0;i<n;i){while(nums[i]>0&&nums[i]<n&&nums[nums[i]-1]!nums[i]){//交换nums[i]和nums[nums[i]-1]int temp nums[nums[i]-1];nums[nums[i]…

C语言课程设计题目(24个选题)

C语言课程设计题目 一、设计要求与设计报告二、检查要求三、打分标准四、提交时间五、选题要求题目列表题目一&#xff1a;职工信息管理系统设计题目二&#xff1a;图书信息管理系统设计题目三&#xff1a;图书管理系统设计题目四&#xff1a;实验设备管理系统设计题目五&#…

回答网友的一个SQL问题

网友问&#xff1a; CODE NAME 1 A 1 B 如何得到下面的值&#xff0c;该如何写SQL CODE NAME 1 AB 1 AB 俺的回答&#xff1a; declare t table(code varchar(50),name varchar(50)) insert into t(code,name) select 1,A union select…

python脚本程序怎么写更优雅?argparse模块巧妙应用

前言 命令行程序&#xff0c;也称CLI程序&#xff0c;另一个直观的名字是脚本程序&#xff0c;简称脚本&#xff0c;由于没有图形用户界面&#xff08;GUI&#xff09;&#xff0c;所以脚本程序常见的交互方式有3种&#xff1a; 1、脚本程序中读取环境变量&#xff0c;比如env…

Spring Security学习

系列文章目录 第一章 基础知识、数据类型学习 第二章 万年历项目 第三章 代码逻辑训练习题 第四章 方法、数组学习 第五章 图书管理系统项目 第六章 面向对象编程&#xff1a;封装、继承、多态学习 第七章 封装继承多态习题 第八章 常用类、包装类、异常处理机制学习 第九章 集…

【深度学习】深度卷积神经网络(AlexNet)

在 LeNet 提出后&#xff0c;卷积神经网络在计算机视觉和机器学习领域中很有名气&#xff0c;但并未起到主导作用。 这是因为 LeNet 在更大、更真实的数据集上训练的性能和可行性还有待研究。 事实上&#xff0c;在 20 世纪 90 年代到 2012 年之间的大部分时间里&#xff0c;…

电线杆上电气组件检测系统源码分享

电线杆上电气组件检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comp…

视频怎么制作成二维码?视频轻松生成二维码的3步操作

现在很多人为了能够更快捷的实现视频内容的分享&#xff0c;会通过将视频生成二维码的方式&#xff0c;让其他人可以通过扫描二维码来查看视频内容。这种方式不需要用户存储视频&#xff0c;扫码就能够在设备上查看视频&#xff0c;有利于提升查看视频的便捷性&#xff0c;可以…

【秋招笔试题】多多排序

解法&#xff1a;简单语法题 package com.sky;import java.util.*;public class Test1 {public static void main(String[] args) {Scanner sc new Scanner(System.in);int N sc.nextInt();int M sc.nextInt();List<String> words new ArrayList<>(N);for (in…

关于TrustedInstaller权限

前言 我们在在删除某些文件时会发现权限不够的情况&#xff0c;那是因为自从 Windows Vista 以来&#xff0c;为了提升安全性&#xff0c;微软对于权限的把控越来越紧。为了对抗恶意软件随意修改系统文件&#xff0c;Trustedinstaller 应运而生。 各权限之间的关系 普通人:Us…

C++STL--------string

文章目录 一、STL介绍二、string1、constructor构造函数2、operator[]方括号运算符重载3、iterator迭代器4、reverse_iterator反向迭代器5、size和length6、capacity7、clear8、shrink_to_fit9、at10、push_back11、append 二、auto类型(C11)1、使用2、真正的价值 三、范围for(…

python全栈学习记录(十八)re、os和sys、subprocess

re、os和sys、subprocess 文章目录 re、os和sys、subprocess一、re1.正则字符2.正则表达式的使用3.group的使用4.贪婪匹配与惰性匹配5.其他注意事项 二、os和sys1.os2.sys 三、subprocess 一、re python中的re模块用来使用正则表达式&#xff0c;正则就是用一系列具有特殊含义…

2024 年最新 Protobuf 结构化数据序列化和反序列化详细教程

Protobuf 序列化概述 Protobuf&#xff08;Protocol Buffers&#xff09;是由Google开发的一种语言中立、平台中立、可扩展的序列化结构数据的方法。它用于在不同系统之间高效地交换数据。Protobuf使用定义文件&#xff08;.proto&#xff09;来描述数据结构&#xff0c;并通过…

Pytest测试实战|执行方式

Pytest测试实战 The pytest framework makes it easy to write small, readable tests, and can scale to support complex functional testing for applications and libraries. 这段话很好地阐述了Pytest的设计思想与强大的特性。在之前阐述了Pytest编写测试用例规范与搜索规…

R包:gplots经典热图

加载R包 # install.packages("gplots")library("gplots")数据 mat <- matrix(rnorm(1200), ncol6)画图1 heatmap.2(xmat)画图2 heatmap.2(xmat, ColvFALSE, dendrogram"row",scale"row",col"bluered",trace"non…

828华为云征文 | 解锁企业级邮件服务,在华为云Flexus x实例上部署Mailcow开源方案

前言 华为云Flexus X实例携手Mailcow开源邮件方案&#xff0c;为企业打造了一个既高效又安全的邮件服务解决方案。Flexus X实例的柔性算力与高性能&#xff0c;是这一方案的坚实基石。它提供CPU内存的灵活定义&#xff0c;以经济型价格实现旗舰级性能&#xff0c;确保邮件服务的…

大模型分布式训练并行技术(一)-概述

近年来&#xff0c;随着Transformer、MOE架构的提出&#xff0c;使得深度学习模型轻松突破上万亿规模参数&#xff0c;传统的单机单卡模式已经无法满足超大模型进行训练的要求。因此&#xff0c;我们需要基于单机多卡、甚至是多机多卡进行分布式大模型的训练。 而利用AI集群&a…

Gitee基本指令操作

目录 1.概念 2. git的基本指令 3. .gitignore 文件 4 . Linux git || gitee || github 1.概念 Git是一种版本控制的软件。 Git是免费且开源的。 Git常被称为 去中心化的分布式的 数据存储。 【其实git也可以进行本地版本控制。对于git&#xff0c;可理解为是一个 本地版本…