【C++】位图及其应用

news2024/11/24 20:49:39

在这里插入图片描述

🚀write in front🚀
📜所属专栏: C++学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言
  • 一.位图
    • 1.一道面试题:
    • 2.位图的概念:
    • 3.位图的模拟实现:
    • 3.位图的应用
  • 二.位图的实际使用场景:
    • 场景1:
    • 场景2.
    • 场景3:
  • 三.库里面的bitset:
  • 总结

前言

  在前面我们简单介绍了哈希和哈希表的概念,并模拟实现了unordered_mapunordered_set,下面我们就来介绍一下哈希的应用

一.位图

  我们先通过一个面试题来引入位图:

1.一道面试题:

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

在这里最先想到了下面两种方法:

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

  上面的方法对于数据量少的数据还是可以解决的,但是对于40亿个整数,也就是160亿个字节还是不够存储的。我们知道,1G差不多就是10亿字节,如果存储在内存里面就需要16G,普通的电脑根本无从下手。而且,这道题问的是在不在的问题,这里就可以通过位图来解决这道题目。

2.位图的概念:

  当面对海量数据时,我们一般的数据结构无法存储那么多的值,要对这些数据进行分析,我们就可以采用位图来对这些数据进行标记不是存储)。位图适用于海量数据,数据无重复的场景,通常用来判断这个数据是否存在。位图采用的就是哈希里面的直接定址法:
在这里插入图片描述
对于整数,最大值也就是2^32 次方,所以这里我们只需要2^ 32次方个数字就可以表示完所有的整数,由于是在不在问题,每一个位置的1表示在,0表示不在即可。所以我们只需要2^32 个比特位即可,也就是2^29个字节,0.5G就可以完成这道面试题。

3.位图的模拟实现:

在我们的vs编译器下,是小端类型,存储是这样的:(低地址存低位)
在这里插入图片描述
这里我们在讲解一下小端存储,在一个整形的内存里面,01 00 00 00,01是地址最低的一个字节,但是每一个字节里面存储的的顺序右和我们平常存的顺序是一样的,比如1是0000000001。举个例子:(左边是低地址)
在这里插入图片描述

在下面的操作里面,为了标记哪个位置是否存在,就要使用按位与和按位或的操作,从而要对1进行左移,但是在这里大家看到01 00 00 00就会觉得奇怪,为什么可以左移呢?其实左移的定义是往高位移动,只是平时我们写的时候习惯了高位在左边,低位在右边的形式。下面我举个例子:

00000000 00000000 00000000 00000001在内存里面是这样存的
00000001 00000000 00000000 00000000
如果我们对1左移10个位置,也就是
00000000 00000100 01000000 00000000

这里就是说编译器在进行左移的时候,先是每一个字节里面左移左移完了发现还没到位就在下一个字节里面继续左移。其实编译器的左移和我们找位置找到的地方是一致的。
在这里插入图片描述

代码实现:

template<size_t N>
class bitset
{
public:

    bitset()
    {
        _a.resize(N / 32 + 1, 0);	//至多多开一个int 空间
    }


    void set(size_t x)
    {
    	//先寻找在哪一个字节里面
        size_t i = x / 32;
        //在寻找在这个字节里面的哪个位置 
        size_t j = x % 32;
        //1左移j个位置就是将那个位置置为1,其他位置置为0
        _a[i] |= (1 << j);
    }

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

        //置0
        _a[i] &= ~(1 << j);
    }

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

private:
    vector<int> _a;
};

这里采用vector来管理位集合的数据,int为4byte,占32个比特位
采用非类型模板参数,来表示要开多少个空间,N/32 + 1,这里防止开的空间不够,所有每次直接+1,至多多开一个整型空间

3.位图的应用

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

二.位图的实际使用场景:

场景1:

给定100亿个整数,设计算法找到只出现一次的整数?
  在这里我们就可以使用两个位图来解决,两个位图也就1G,也不算特别多。我们可以通过两个位图的同一位置的组合来判断出现过几次,比如第一个位图pos位置为0,第二个位图的pos位置为1,就说明其只出现过一次。

template<size_t N>
	class twobitset
	{
	private:
		BitSet<N> bt1;
		BitSet<N> bt2;

	public:
		void set(size_t n)
		{
			size_t i = n / 32;
			size_t j = n % 32;
			
			//出现一次的
			if (!bt1.test(n) && !bt2.test(n))
			{
				bt2.set(n);
			}
			
			//出现两次的
			else if (!bt1.test(n) && bt2.test(n))
			{
				bt1.set(n);
			}
		}

		bool is_once(size_t n)
		{
			return !bt1.test(n) && bt2.test(n);
		}
	};
}
void isOnce()
{
	bitSet::twobitset<100> tbt;
	int arr[] = { 1,2,3,3,44,6,6,4,4,6,3,1,9,6,8 ,3,22 };
	for (auto e : arr)
	{
		tbt.set(e);
	}

	for (auto e : arr)
	{
		if (tbt.is_once(e))
			cout << e << " ";
	}cout << endl;
}

场景2.

1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
  其实这里和上面的的两个位图是一样的,由于00 01 10 11可以表示出四种情况,我们用00表示没有,01表示出现一次,10表示出现两次,11表示两次以上即可:

template<size_t N>
class twobitset
{
public:
    void set(size_t x)
    {
        if (!bt1.test(x) && !bt2.test(x))
        {
            //00 ->01
            bt2.set(x);
        }
        else if (!bt1.test(x) && bt2.test(x))
        {
            //01->10
            bt2.reset(x);
            bt1.set(x);
        }
        else if (bt1.test(x) && !bt2.test(x))
        {
            //10->11
            bt1.set(x);
            bt2.set(x);
        }
    }
    //00
    //01
    //11
    bool lessTwo(size_t x)
    {
        if ((!bt1.test(x) && bt2.test(x)) || (bt1.test(x) && !bt2.test(x)))
        {
            bt1.reset(x);
            bt2.reset(x);
            return true;
        }
        return false;
    }

private:
    bitset<N> bt1;
    bitset<N> bt2;
};

//模拟
void LessTwo()
{
	bitSet::twobitset<10> bt;
	int arr[] = { 1,1,2,2,3,3,5,5,5,9,7,7,7,8,8,8,8,1 };
	for (auto e : arr)
	{
		bt.set(e);
	}

	for (auto e : arr)
	{
		if (bt.lessTwo(e))
		{
			cout << e << " ";
		}
	}cout << endl;
}

场景3:

给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
  这里有两种方法,其一就是装到两个位图里面比较即可,
其二就是将一个装到位图里面,另一个以文件的形式读取数据并且不断比较,相同的就取出来。但是这里存在重复的问题,所以每从位图里面找到一个交集,就将他reset去掉该位置的存在标记,这样就可以避免取到重复数据。

三.库里面的bitset:

  其实库里面有位图的实现了,我们只需直接使用即可。bitset

在这里插入图片描述

总结

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
C语言学习
算法
智力题
初阶数据结构
Linux学习
C++学习
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

【算法-动态规划】钢条切割问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

python一行命令搭建web服务,实现内网共享文件

python一行命令搭建web服务&#xff0c;实现内网共享文件 有时候我们在本地电脑访问自己的虚拟机的时候&#xff0c;可能因为某些原因无法直接CV文件到虚拟机。但此时我们又想上传文件到虚拟机&#xff0c;如果虚拟机和本地电脑可以互通。那么我们可以直接通过python来启动一个…

安全巡检管理系统—隐患排查治理

安全管理越来越重要&#xff0c;每个生产企业都需要一个安全隐患排查治理小程序&#xff01;利用凡尔码平台搭建安全巡检管理系统主要有以下四个功能 1、制定巡检计划&#xff1a;安全巡检管理系统可以帮助用户制定巡检计划&#xff0c;用户可以根据需要创建不同的计划&#xf…

浅谈MDK, IAR,CLANG和GCC的局部变量字节对齐处理差异(2023-10-13)

视频&#xff1a; https://www.bilibili.com/video/BV1CB4y1Z7kA 浅谈MDK, IAR, CLANG和GCC的局部变量字节对齐处理差异 问题由来&#xff1a; 早期这个帖子里面的局部变量对齐仅测试了MDK AC5&#xff0c;但项目中使用AC6发现了新问题&#xff0c;看来AAPCS规约研究的还是不…

Discuz大气游戏风格模板/仿lol英雄联盟游戏DZ游戏模板GBK

Discuz大气游戏风格模板&#xff0c;lol英雄联盟游戏模板&#xff0c;DZ游戏娱乐模板GBK。模板名称&#xff1a;lol英雄联盟游戏&#xff08;m0398_lol&#xff09; 下载地址&#xff1a;https://bbs.csdn.net/topics/617408069

多维高斯分布(多元正态分布)的概率密度函数和最大似然估计

多元高斯分布的概率密度函数 f μ , Σ ( x ) 1 ( 2 π ) D / 2 1 ∣ Σ ∣ 1 / 2 e x p { − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) } f_{\mu, \Sigma}(x)\frac{1}{(2 \pi)^{D/2}} \frac{1}{|\Sigma|^{1/2}} exp\{-\frac{1}{2}(x-\mu)^T \Sigma ^{-1}(x-\mu)\} fμ,Σ​(x)…

车载电子电器架构 —— 车载芯片技术简介

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

芯片制造:一颗芯片到底是如何诞生的(下)

目录 背景 芯片制造&#xff1a;晶圆厂的王国 上游&#xff1a;晶圆材料准备 中游&#xff1a;晶圆加工过程 下游&#xff1a;封装与测试 产业链分工视角&#xff1a;设计、制造、封装、测试的分工合作 小结 背景 上一讲&#xff0c;我带你从市场需求分析开始&#xff0…

嵌入式开发学习之STM32F407串口(USART)收发数据(三)

嵌入式开发学习之STM32F407串口&#xff08;USART&#xff09;收发数据&#xff08;三&#xff09; 开发涉及工具一、选定所使用的串口二、配置串口1.配置串口的I/O2.配置串口参数属性3.配置串口中断4.串口中断在哪里处理5.串口如何发送字符串 三、封装串口配置库文件1.创建头文…

洛谷【入门6】函数与结构体-P5735 【深基7.例1】距离函数

## 题目描述 给出平面坐标上不在一条直线上三个点坐标 (x1​,y1​),(x2​,y2​),(x3​,y3​)&#xff0c;坐标值是实数&#xff0c;且绝对值不超过 100.00&#xff0c;求围成的三角形周长。保留两位小数。 对于平面上的两个点 (x1​,y1​),(x2​,y2​)&#xff0c;则这两个点…

【C++】哈希对unordered_map和unodered_set的封装

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a; C学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我最大…

第9期ThreadX视频教程:自制个微秒分辨率任务调度实现方案(2023-10-11)

视频教程汇总帖&#xff1a;【学以致用&#xff0c;授人以渔】2023视频教程汇总&#xff0c;DSP第12期&#xff0c;ThreadX第9期&#xff0c;BSP驱动第26期&#xff0c;USB实战第5期&#xff0c;GUI实战第3期&#xff08;2023-10-11&#xff09; - STM32F429 - 硬汉嵌入式论坛 …

“之江创客”聚焦农村电商创新发展 扎实助推共同富裕

10月10日下午&#xff0c;由商务部中国国际电子商务中心指导&#xff0c;浙江省商务厅等十个部门主办&#xff0c;浙江省电子商务促进中心联合丽水市商务局承办的“之江创客”2023全球电子商务创业创新大赛农村电商赛区决赛暨颁奖典礼在丽水圆满落幕。浙江省商务厅党组成员、副…

Folium笔记: Popup

1 介绍 在 folium 中&#xff0c;Popup 是一个用于在地图上显示附加信息的对象。当在地图上点击一个标记&#xff08;例如&#xff0c;一个点或者一个形状&#xff09;时&#xff0c;Popup 会显示出来。Popup 可以包含纯文本&#xff0c;但也可以包含HTML代码 2 主要参数 htm…

安捷伦E9326A/E9327A射频传感器

出售Agilent安捷伦E9326A/E9327A射频传感器 E9326A 是 Agilent 使用的 18 GHz 0.1 瓦射频传感器。电子测试设备传感器测量波形的功率&#xff0c;例如多音和调制射频 (RF) 波形。传感器使用二极管检测器收集高度精确的调制测量值。 1.5 MHz 视频带宽&#xff0c;非常适合蓝牙?…

Python算法练习 10.14

leetcode 2095 删除链表的中间节点 给你一个链表的头节点 head 。删除 链表的 中间节点 &#xff0c;并返回修改后的链表的头节点 head 。 长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点&#xff08;下标从 0 开始&#xff09;&#xff0c;其中 ⌊x⌋ 表示小于或等于…

androidx和v4包资源冲突解决方法

一、资源包会报如下错误&#xff1a; 错误类似 (androidx.core:core:1.10.0) 和 (com.android.support:support-compat:24.2.0) 表示资源重复&#xff0c;不知调用androidx包下面的&#xff0c;还是v4包下面的 Duplicate class android.support.v4.app.INotificationSideCha…

恒温区检测热电偶

声明 本文是学习GB-T 4000-2017 焦炭反应性及反应后强度试验方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 7— 进气口&#xff1b; 8— 测温热电偶。 图 A.1 单点测温加热炉体结构示意图 A.3 温度控制装置 控制精度&#xff1a;(11003)℃。…

RK3568 DRM显示框架

一.简介 显示子系统是 Rockchip 平台显示输出相关软硬件系统的统称&#xff0c;它包括 VOP&#xff08;比较老的平台叫 LCDC&#xff0c;比如 RK3188、RK3066&#xff09;和 RGB、BT1120、BT656、I8080&#xff08;MCU 显示接口&#xff09;&#xff0c;LVDS、MIPI DSI、EDP、…

PyTorch模型INT8量化基础

PyTorch模型INT8量化基础 最基础的Tensor量化校准两种不同的量化方案每张量和每通道量化方案量化后端引擎配置QConfigTensor量化Post Training Static Quantization (训练后静态量化)fuse_model:融合网络中的一些层 设置qCONFIGprepare: 定标 &#xff1a;scale 和 zero_point喂…