【C++进阶】bitset位图介绍以及模拟实现

news2024/9/22 15:39:39

文章目录

  • 位图介绍
    • 一、位图的引入
    • 二、位图的概念
  • 位图模拟实现
    • 一、构造函数
    • 二、set,reset,test函数
    • 三、代码测试
    • 四、完整代码

位图介绍

一、位图的引入

先来看下边一道面试题:

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

经过我们之前的学习,我们可能会有以下的思路:

  1. 对这些数进行排序,再通过二分算法,查找这个数是否存在
  2. 插入到unordered_set中,使用find函数查找是否存在

上述方法看起来还不错,二分查找算法时间复杂度为logN,而插入到unordered_set中时间复杂度为O(N),而查找时时间复杂度为O(1),但是都有一个问题就是要将空间不足,40亿个无符号整形,需要160亿字节的空间,大概就是16GB的空间,一般计算机的内促都是4G或者8G,所以空间不足,此时就有了位图的方法来解决:

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

比如:
在这里插入图片描述
对于上图来说,有一个整形数组,我们可以使用直接定址法对数组的数据进行映射,但是与之前不同的是,此时只是使用一个比特位来代表一个整形数据,当这个数存在时,比特位置1,不存在时,比特位置0,此时就可以大大节省空间资源,无符号整数只有2的32次方个,所以最多开2的32次方个空间,一个空间为一个比特,所以最终只需要512MB的空间。
但是我们不能按照位来空间,最少必须一个字节,所以我们就每次开一个字节的空间,也就是8个比特位,将8位当做一个整体来处理,对要保存的数据除8就是第几个字节,对保存的数据模8就是在这个字节中的第几个位置。

二、位图的概念

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

那么位图还有哪些应用呢?

  1. 快速查找某个数据是否在一个集合中
  2. 排序 + 去重
  3. 求两个集合的交集、并集等
  4. 操作系统中磁盘块标记

位图模拟实现

一、构造函数

由于不能按位开空间,所以我们选择每次开一个字节的空间,由于有范围最大为N,一位关联一个数据,所以需要开N/8个字节的空间,但是有时可能不能整除,所以要开N/8+1个字节的空间。
所以直接在构造函数中开好空间:

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

二、set,reset,test函数

set函数的作用是对位图中的某一位进行填充
i就表示是第几个字节,而j表示该位在该字节中的第几位,所以对1进行左移j位后与该字节按位或,按位或的作用时不论该位为0还是为1,都将该位变为1.
在这里插入图片描述

		void set(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			_bits[i] |= (1 << j);
		}

reset的作用是将某一位清空
同样的将要清空的那一位置为0,进行按位与,不论原本该位是0还是1,都将该位置0
在这里插入图片描述

		void reset(size_t x)
		{
			int i = x / 8;
			int j = x % 8;
			_bits[i] &= ~(1 << j);
		}

test的作用是检测位图中某一位是否存在
在这里插入图片描述

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

三、代码测试

	void test_bit_set1()
	{
		bitset<100> bs1;
		bs1.set(8);
		bs1.set(9);
		bs1.set(20);

		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;

		bs1.reset(8);
		bs1.reset(9);
		bs1.reset(20);

		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
	}

在这里插入图片描述

四、完整代码

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

	void test_bit_set1()
	{
		bitset<100> bs1;
		bs1.set(8);
		bs1.set(9);
		bs1.set(20);

		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;

		bs1.reset(8);
		bs1.reset(9);
		bs1.reset(20);

		cout << bs1.test(8) << endl;
		cout << bs1.test(9) << endl;
		cout << bs1.test(20) << endl;
	}

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

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

相关文章

SAR ADC version2 ——ADC背景介绍

目录&#xff1a; ADC常用指标分类 静态性能&#xff1a;微分非线性&#xff1a;DNL 积分非线性&#xff1a;INL 仿真测试DNL&#xff1a;&#xff08;码密度法&#xff09;&#xff08;code density&…

OpenCV 入门教程:像素访问和修改

OpenCV 入门教程&#xff1a;像素访问和修改 导语一、像素访问1.1 获取图像的大小1.2 访问图像的像素值1.3 修改图像的像素值 二、示例应用2.1 图像反转2.2 阈值化操作 三、总结 导语 在图像处理和计算机视觉领域&#xff0c;像素级操作是非常重要和常见的任务之一。通过像素访…

Python——将F12得到的请求头转换成其对应json格式

问题引入 最近在鼓捣爬虫准备爬爬学校网站&#xff0c;用到pthon的requests库发送get请求时需要提供headers. 需要将请求头转换成json格式的数据。json格式如下所示 headers{"Path":"xxx","User-Agent":"xxx" } 但是从网页上f12复…

21-注册中心与配置中心Nacos

已经使用过了Spring cloud提供的Geteway、openFeign。 1、注册中心与配置中心 1.1、注册中心 相当于通讯录,让应用之间相互认识。 用途: 实例的健康检查。 路由转发:为了控制成本,会对机器做动态扩容,此时IP就不固定了。 远程调用。 1.2、配置中心 动态修改线上的配…

深入解析MySQL视图、索引、数据导入导出:优化查询和提高效率

目录 1. 视图&#xff08;View&#xff09;&#xff1a; 什么是视图&#xff1f; 为什么要使用视图&#xff1f; 视图的优缺点 1) 定制用户数据&#xff0c;聚焦特定的数据 2) 简化数据操作 3) 提高数据的安全性 4) 共享所需数据 5) 更改数据格式 6) 重用 SQL 语句 …

十一.Redis发布订阅

Redis发布订阅(pub/sub)是一种消息通信模式&#xff1a;发布者(pub)发送消息&#xff0c;订阅者(sub)接受消息。此种模式下&#xff0c;消息发布者和订阅者不进行直接通信&#xff0c;发布者客户端向指定的频道&#xff08;channel&#xff09; 发布消息&#xff0c;订阅该频道…

【MQTT】Esp32数据上传采集:最新mqtt插件(支持掉线、真机调试错误等问题)

前言 这是我在Dcloud发布的插件-最完整Mqtt示例代码&#xff08;解决掉线、真机调试错误等问题&#xff09;&#xff0c;经过整改优化和替换Mqtt的js文件使一些市场上出现的问题得以解决&#xff0c;至于跨端出问题&#xff0c;可能原因有很多&#xff0c;例如&#xff0c;合法…

MySQL基础篇第3章(基本的SELECT语句)

文章目录 1、SQL概述1.1 SQL背景知识1.2 SQL分类 2、SQL语言的规则与规范2.1 基本规则2.2 SQL大小写规范 &#xff08;建议遵守&#xff09;2.3 注释2.4 命名规则2.5 数据导入指令 3、基本的SELECT语句3.0 SELECT...3.1 SELECT...FROM3.2 列的别名3.3 去除重复行3.4 空置参与运…

营销人累了看看这5部影片吧!保你再燃激情

市场瞬息万变&#xff0c;做营销需不断学习充电&#xff0c;除了看书听课之外看电影也是学习营销的有效方式。今天小马识途营销顾问给大家推荐5部市场营销人员必看的高评分电影&#xff0c;相信看完之后&#xff0c;会对你今后的发展影响深远&#xff01;话不多说直接上干货&am…

并发编程 - Event Driven 设计模式(EDA)

文章目录 EDA 概述初体验EventEvent HandlersEvent Loop 如何设计一个Event-Driven框架同步EDA框架设计MessageChannelDynamic RouterEventEventDispatcher测试同步EDA架构类图 异步EDA框架设计抽象基类 AsyncChannelAsyncEventDispatcher 并发分发消息测试 EDA 概述 EDA&…

【计算机网络】第 2 课 - 计算机网络的性能指标

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、性能指标 2.1、速率 2.2、带宽 2.3、吞吐量 2.4、时延 2.5、时延带宽积 2.6、往返时间 2.7、利用率 2.8、丢…

【Cartopy学习系列】Cartopy中的投影类型总结

一、PlateCarree&#xff08;圆柱投影&#xff09; PlateCarree 是Cartopy的默认投影&#xff0c;投影将地物投影到圆柱面上再展开&#xff0c;常用来绘制世界地图。该投影具有经线或纬线方向等度数的特点&#xff0c;亦称等经纬度投影。 class cartopy.crs.PlateCarree(cent…

【Kafka】Kafka消费者

【Kafka】Kafka消费者 文章目录 【Kafka】Kafka消费者1. 消费方式1.1 消费者工作流程1.2 消费者组原理1.3 消费者组初始化流程1.4 消费者组详细消费流程1.5 消费者重要参数 2. 消费者API2.1 独立消费者案例2.2 订阅分区2.3 消费者组案例 1. 消费方式 pull(拉)模式&#xff1a;…

Linux上查看外接USB设备类型

最近遇到一个问题&#xff0c;需要在shell脚本中识别当前显示器的USB触屏线是否插入&#xff0c;并读取显示器名称&#xff0c;以确定是否是想要的。 解决思路&#xff1a; lsusb命令可以列出所有的外接USB设备&#xff1a; 其中 “Atmel Corp. Atmel maXTouch Digitizer” 即为…

rabbitmq使用springboot实现direct模式

一、 Direct模式 类型&#xff1a;direct特点&#xff1a;Direct模式是fanout模式上的一种叠加&#xff0c;增加了路由RoutingKey的模式。 二、coding Ⅰ 生产者 1、引入相应的pom文件 pom.xml <?xml version"1.0" encoding"UTF-8"?> <pro…

Linux 学习记录48(QT篇待完成)

Linux 学习记录48(QT篇) 本文目录 Linux 学习记录48(QT篇)一、1.2. 二、三、四、练习1. 自制文本编辑器(0. main.cpp(1. txt_window.h(2. txt_window.cpp 2. 登录界面完善 一、 1. 2. 二、 三、 四、 练习 1. 自制文本编辑器 (0. main.cpp #include "txt_window.h…

JavaWeb 笔记——5

JavaWeb 笔记——5 一、Filter1.1、概述1.2、Filter快速入门1.3、Filter执行流程1.4、Filter使用细节1.5、Filter-案例-登陆验证 二、Listener2.1、Listener概述与分类2.2、ServletContextListener使用 三、AJAX3.1、AJAX概述3.2、AJAX快速入门3.3、使用Ajax验证用户名是否存在…

《阿里大数据之路》研读笔记(3)事实表

不理解可以先看看这个例子 例子里的start_time可以看成下单时间 end看成确认收货时间 这个例子中累计快照事实表和拉链表类似 图解HIVE累积型快照事实表_累积快照事实表_小基基o_O的博客-CSDN博客 累计快照事实表 我的理解是 根据上面的例子 就是一行代表多个业务过程 每个…

day18 哈希表

题目一&#xff1a;两个数组的交集 题目描述 int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){//哈希表 int arr_hash[1000] {0};int *arr_result (int *)malloc(sizeof(int)* nums1Size);*returnSize 0;for(int i 0;i < nu…

强化学习|底层逻辑与本质 引导式学习

强化学习的本质是什么&#xff0c;底层逻辑是什么&#xff1f; 强化学习的本质是一个智能体通过与环境的交互&#xff0c;通过尝试和错误的方式学习如何采取行动来最大化累积奖励。它的底层逻辑基于马尔可夫决策过程&#xff08;Markov Decision Process&#xff0c;MDP&#x…