C++位图(Bitmap)

C++位图详解(BitMap) 题目:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快 速判断一个数是否在这40亿个数中。 【腾讯】思路:这道题首先要判断40亿个不重复的无符号整数究竟占多大的内存,因为太大的内存我们无法加载到现有的计算机中。一个整数是4个字节,40亿个整数就是160亿个字节,也就相当于16G内存,就一般的计算机而言很难实现这个加载,所以我们可以采取以下两种方案,一种是分割,一种是位图。方法:①分割 阅读详情

一.逻辑运算符

        首先普及一下将要用到的逻辑运算符号:

【与】运算符号为 & ,运算法则为遇0得0。也就是说只要有0,结果即为0。

【或】运算符号为 | ,就是一个竖线,运算法则为遇1得1。也就是说,只要有1,结果就为1。

【非】预算符号为 ~,就是一个波浪线,运算法则为按位取反,也就是遇1取0,遇0取1,即 ~1 = 0 , ~0 = 1;

【异或】运算符号为 ^,就是一个乘方符号,运算法则为相同取0,不同取1。异或运算,关键在异上面,异为1,否则为0。

二.位图

1.bitmap的概念

        位图 (Bitmap) 是一种基于位操作的数据结构,用于表示一组元素的集合信息。它通常是一个仅包含0和1的数组,其中每个元素对应集合中的一个元素。位图中的每个位(或者可以理解为数组的元素)代表一个元素是否存在于集合中。当元素存在时,对应位的值为1;不存在时,对应位的值为0。位图常用于判断某个元素是否属于某个集合,或者对多个集合做交集、并集或差集等集合运算。

        可能这么多听起来很复杂,其实总

结下来就这个意思:

        位图本质是个数组,用来存放0和1。

        位图通过自身数组中的每个位来代表集合(我们要处理的数据)中的元素,每个位是0或1,代表元素的存在与否(0,不存在;1,存在)。

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

1.首先当然可以遍历这40亿个数,这样效率会太低了,肯定直接pass掉.

2.也可以考虑搜索树或者哈希表,操作之前一定要把数据先存下来构建树或表。但是仔细一想,40亿个数,占多少空间?

40亿个无符号整数,每个大小4个字节,则一共占用160亿字节。

1GB = 1024 MB, 1MB  = 1024KB, 1KB = 1024Byte(字节).

所以一共占用16000000000/1024/1024/1024≈14.9G.

所以要用这些方法的话一上来就占用14.9G的系统内存,大多数电脑是吃不消的,更别说搜索树结点还存其他属性信息,现在内存16G的电脑也不算很多。这肯定不行的.

3.当然还可以存在磁盘上,进行外排序+二分查找。但是想一下,这一切是在磁盘上进行,磁盘的速度可是非常慢的,而且要对这么多数据排序,以及在磁盘上进行二分查找,无论代码还是时间都是复杂和比较慢的.

下一个方法,就是我们大名鼎鼎的位图来解决了,具体是怎么样的呢?

        首先,我们要给数组开辟一块空间,这片空间我们开多少呢,要根据数据范围开空间,而不是数据个数。

        这个我相信大家都能理解,毕竟如果只有两个数,一个是1,一个数是40亿,按数据个数开两个空间的话只能存下1和2,40亿肯定是存不下的。

        所以无符号整型的数据范围是0~2^32-1,所以我们要开这么大的空间.那么一共多大呢?

        由于我们是使用比特位进行表示每一个数是否存在的,所以相当于是2^32-1个比特位。由于1byte=8bit.根据上面所说,一共占用(2^32-1)/8/1024/1024/1024=0.5GB=512MB. 

        所以我们开好空间以后,我们只需要将数对应的位置为1即可.

        比如数据{1,4,9,15,17,23},在位图中是什么样的?

        这样到时候直接判断对应位置是不是1即可判断某个数是否存在.

2.bitmap模拟实现

        主要包含三个核心接口:设置(设为1)、重置(设为0)、判断(是0还是1)。

#include<iostream>
#include<vector>
using namespace std;
 
namespace hyx
{
    //N代表数据范围
	template<size_t N>
	class bit_set
	{
	public:
		bit_set()
		{
			_bits.resize(N / 8 + 1, 0);
		}
		void set(size_t x)
		{
			//由于一个组是char,所以x/8是计算在哪个char组里
			size_t i = x / 8;
			//一个char里有8位,x%8是计算出在char组里面的具体哪一位
			size_t j = x % 8;
			//这个建议大家画图理解,首先_bits[i]是对应的char组,然后1<<j,其实是将1向左移动了j位,然后再或等,这样就把对应位置上的数置为1了,可以画图理解.
			_bits[i] |= (1 << j);
		}
		void reset(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;
			//也是先1向左移动j位,然后再按位取反,此时除了目标位是0,别的位都是1.然后再&上这个数,任何数&1都是它本身,&0都是0.所以此时将目标位设置为0了
			_bits[i] &= ~(1 << j);
		}
		bool test(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;
			//任何数&1都是它本身,因为我们可以利用这一点来判断目标位是0还是1.
			//注意此时不再需要加等于号了,因为这是判断,不是修改。
			return _bits[i] & (1 << j);
		}
	private:
		vector<char> _bits;
	};
}

3.常见bitmap面试题

1.给定100亿个整数,设计算法找到只出现一次的整数?
首先100亿个整数会不会有空间的问题?答案是肯定不会的,因为开空间和数据范围有关系,和数据个数没有关系,100亿个整数,每个数的范围都是42亿(2^32-1)之内,不会说有100亿个不重复的整数.

首先问题是找出现一次的整数,很明显是个key-value模型。那这至少需要两个位图了。所以就需要建立双位图解决.

既然求出现一次,那么肯定是以下三种情况:(左边次数,右边对应的位图状态)

0次                     00

1次                     01

2次及以上          10

所以上面可知,第二个位图是由两个位进行表示.这样又得需要各种控制,也是不太方便.

其实位图也是一个数据结构,STL库中也有对应的容器——bitset.

 那我们直接用两个位图分别表示这两个位不就可以了吗,当然!

所以我们要自己建立一个有两个位图的类,如下

整体思路是:依次判断两个位:

1.若为00,说明这个数一次也没出现过,将其改为01.即将第二个位图设为1.

2.若为01,说明这个数出现了一次,将其改为10,即第一个位图设为1,第二个位图设为0.

 后面可以写一个成员函数来输出符合条件的数:
 

template <size_t N>
class twobitset
{
public:
	void set(size_t x)
	{
		bool inset1 = _bs1.test(x);
		bool inset2 = _bs2.test(x);
		//00
		if (inset1 == false && inset2 == false)
		{
			//->01
			_bs2.set(x);
		}
		else if (inset1 == false && inset2 == true)
		{
			//->10
			_bs1.set(x);
			_bs2.reset(x);
		}
	}
		void print_once_num()
		{
			for (int i = 0; i < N; i++)
			{
				//筛选出两个位图为01的数
				if (_bs1[i] == false && _bs2[i] == true)
				{
					cout << i << endl;
				}
			}
		}
private:
	bitset<N> _bs1;
	bitset<N> _bs2;
};
void test_oncenum()
{
	int a[] = { 1,1,2,3,4,5,5,5,6,6,6,6,7,9,22 };
	twobitset<100> bs;
	for (auto e : a)
	{
		bs.set(e);
	}
	bs.print_once_num();
}
2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集? 

这道题比较简单,思路是建立两个位图,然后分别把两个文件里的数据set到位图里,然后最后将两个位图&一下,然后再从最后的结果中找位是1的即可(利用test).

3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数.
这个题和1题类似,无非就是多了一种状态:3次及3次以上。最后对应的状态是以下这样:

0次                     00

1次                     01

2次                     10

3次及3次以上     11

然后要在twobitset的set中多加一个判断条件:当位图位10时,下一次改为11.
 

		//10
		else if (inset1 == true && inset2 == false)
		{
			//->11
			_bs2.set(x);
		}

然后输出的时候变化条件为bs1[i]==true和bs2[i]==true(11)即可.

Bitmap详解 RGB色彩模式是工业界的一种颜色标准,是通过对红、绿、蓝三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。对一种颜色进行编码的方法统称为“颜色空间”或“色域”。用最简单的话说,世界上任何一种颜色的“颜色空间”都可定义成一个固定的数字或变量。RGB(红、绿、蓝)只是众多颜色空间的一种。采用这种编码方法,每种颜色都可用三个变量来表示-红色绿色以及蓝色的强度。 阅读详情

相关推荐

你知道什么是 BitMap 吗?

BitMap(位图)是一种数据结构,用于表示一个特定范围内的二进制位(0或1)序列。在计算机科学中,BitMap通常用于高效地表示大量的布尔值,每个位代表一个布尔值,可以表示存在或不存在、true或false等状态。

激流丶的博客 2653

Bitmap类用法 详细说明

1.    BitMap类

ymangu的专栏 3万+

c/c++ 数据结构之位图(bitmap)详解

1.  概述 位图(bitmap)是一种非常常用的结构,在索引,数据压缩等方面有广泛应用。本文介绍了位图的实现方法及其应用场景。 2. 位图实现 (1)自己实现 在位图中,每个元素为“0”或“1”,表示其对应的元素不存在或者存在。 #define INT_BITS sizeof(int) #define SHIFT 5 // 2^5=32 #define MASK

hustyangju的足迹 1万+

【数据结构】BitMap

BitMap,即位图,使用每个位表示某种状态,适合处理整型的海量数据。本质上是哈希表的一种应用实现,原理也很简单,给定一个int整型数据,将该int整数映射到对应的位上,并将该位由0改为1。

dilireba666的博客 4543

邓俊辉《数据结构C++》第二章课后习题中位图Bitmap的三个接口实现代码解释

void set(int i); //将第i位置为true(将整数i加入当前集合) void clear(int i); //将第i位置为false(从当前集合中删除整数i) bool test(int i); //测试第i位是否为true(判断整数i是否属于当前集合) 教材给的实现代码如下: void set(int k) { expand(k); M[k >> 3] |= (0x80 >> (k & 0x07)); } void clear(int k) { expan

weixin_45716046的博客 863

逆向工程实战:手把手教你破解药监局网站的动态数据加载机制(Python+Chrome开发者工具)

本文详细介绍了如何利用Python和Chrome开发者工具逆向破解药监局网站的动态数据加载机制。通过分析Ajax请求、解析JSON响应数据以及处理动态参数,帮助开发者高效采集动态加载内容,适用于爬虫开发与数据分析场景。

weixin_30832143的博客 68

位图(Bitmap)的C++实现

本文转载于:https://blog.youkuaiyun.com/MBuger/article/details/61628572 1、位图(Bitmap)简介 位图是一种非常常见的结构,它使用每个二进制位来存放一个值的状态,正因为这个性质,它经常被用在数据压缩或者是索引等方面。 有这样一道题:给40亿个不重复的无符号整数,没有经过排序,然后再给一个树,如何快速判断这个数是否在40亿个数...

蓬莱道人的博客 2904

使用LaTex写IEEE trans 论文的参考文献(bib)

(1)在.TeX文件的最下方添加这几行内容,主要为生成tran形式的参考文献,第二行为参考文献名称,我命名为reference.bib,所以写的是reference,要根据自己的命名改写。(5)如果要在文中引用的话,就在.tex文件中添加\cite{},中括号里面内容为方框圈出来部分,但引用之后,在参考文献后面会出现[1]这样的标识,不知道为什么。(4)完成(3)以后,点击工具-命令-LaTeX,编译,然后按照此步骤LaTeX-bibtex-LaTeX-LaTeX,就可以完成参考文献的导入。

qq_45884215的博客 6259

BITMAP是C++中定义的位图结构体 HBITMAP是Windows中使用的位图句柄 CBitmap是MFC封装的位图类

一:理解 BITMAP是C++中定义的位图结构体 HBITMAP是Windows中使用的位图句柄 CBitmap是MFC封装的位图类 二:相互转换 1、HBITMAP->CBitmap  方法一: HBITMAP hBitmap=(HBITMAP)::LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); C...

BlueMan 1066

PFC中pb模型实战:从胶结参数设置到破坏模拟全流程解析

本文详细解析了PFC软件中平行胶结模型(PB模型)的实战应用全流程。从胶结参数(pb_kn, pb_ks, pb_ten等)的物理意义与精准赋值入手,深入探讨了模型构建、胶结施加以避免初始损伤的技巧,并系统介绍了破坏过程的监测、阈值判定方法以及高级可视化与常见问题诊断。旨在帮助岩土工程与颗粒材料研究者掌握从参数调试到破坏模拟的核心操作,提升数值模拟的准确性与效率。

php55的博客 1075

从安装Eclipse 开始 开发第一个 CDS View

一篇超级简单快速的 创建CDS VIEW 入门步骤介绍文章。

IT小职员 4249

【Cpp】位图Bitmap

【代码】【Cpp】位图Bitmap。

AntigravityC的博客 294

如何在OBS中添加实时时间戳:Lua脚本配置教程(附效果展示)

本文详细介绍了如何在OBS中通过Lua脚本配置实时时间戳功能,包括环境准备、脚本获取、安装配置及高级定制。适用于直播和视频录制场景,提供精准回溯和风格自定义,支持多平台适配和性能优化,是专业制作的必备技巧。

day7的博客 1045

C++位图 | bitmap

再说C++位图之前,我们先看一个经典的面试题。给40亿个不重复的且无序的 unsigned int 整数,然后给出一个整数,判断这个数是否在这40亿个数中?空间换时间借助数组0和1那我们就可以这样设计了。用数组的下标索引值表示数字,如果有则对应位设置为 1,否则为 0。那我们就创建一个40亿大小的数组吧。数组存放什么类型的数据呢?bool?char?int?short?都不太好,就算只占一个字节的bool类型,也有8bit,而我们只需1bit表示是否存在。即存在为1,不存在为0。这样。

qq_62390970的博客 382

保姆级教程:用GROMACS 2022.4的拉伸模拟(SMD)加速蛋白-蛋白组装过程

本文详细介绍了如何使用GROMACS 2022.4的拉伸分子动力学模拟(SMD)技术加速大蛋白组装过程。通过CHARMM36力场和SMD技术,将传统需要数月的蛋白结合过程缩短至数天,大幅提升模拟效率。文章包含参数设计、索引组创建、周期性边界处理等实战技巧,并提供了完整的GPU加速工作流和常见问题解决方案。

weixin_30338481的博客 446

部署OpenClaw时设置环境变量提示export: not valid in this context的完整解决方案

OpenClaw环境变量设置错误解决方案 问题概述 在部署OpenClaw时设置环境变量出现"export: not valid in this context"错误,通常由以下原因导致: 在非交互式shell中使用export命令 在命令替换或管道中使用export 脚本文件包含Windows换行符(CRLF) 解决方案 修正脚本执行方式:确保export命令在正确的shell上下文中使用 使用source命令:通过. setup_openclaw.sh或source setup_op

博客 458

C++实现BitMap位图类

bitmap意为位图,它的每一位用于存放状态,适用于大规模并且不重复的数据,判断某个数据是否存在于位图之中。 之前看过一道腾讯的面试题,有两组数据分别是40亿个QQ号码和60亿个QQ号码,需要查找它们之间重合的数据。如果使用暴力查找一一匹配的话,时间和空间是都吃不消,时间和空间的复杂度很高,很不适用;如果使用分治法分批处理的话,内存可以降低,但是时间复杂度依然很高,也不太适用。如果使用位图的话,就可以很好的解决这个问题,时间空间上都吃的消。 在C++中,整型占32位4个字...

m0_64428335的博客 3583

提示词驱动的智能合同生成与审核

第1章:核心概念与背景 1.1.1 问题背景 1.1.1.1 合同生成与审核的需求 合同作为商业和法律领域中的基本工具,其生成和审核过程至关重要。传统的合同生成往往依赖于法律专业人士的手工撰写,这不仅耗时耗力,而且容易出现错误。此外,合

AI天才研究院 1002

C++----bitmap位图的使用

位图()是一种的存储结构,常用于节省内存、进行快速查找、去重或集合操作。

w_z_j 985

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C++:位运算和位图bitmap

位运算和位图位运算总结移位运算位运算应用举例位图 位运算总结 移位运算 移位运算是双目运算符,两个运算分量都是整形,结果也是整形。 “<<” 左移:右边空出的位上补0,左边的位将从首位挤掉,其值相当于乘2。 ">>"右移:右边的位被挤掉。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。 二进制补码运算公式: -x = ~x + 1 = ~(x-1) -(~x) = x+1 ~(-x) = x-1 x+y = x - ~y - 1

MARSHCW的博客 1680

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C++位图(Bitmap)实现详解:海量数据处理利器从原理到实战

位图是一种利用比特位标记数据存在性的紧凑数据结构,其核心原理是通过位运算在固定内存空间内高效表示大规模集合。这种‘空间换时间’的设计思想,在需要处理海量数据且状态仅为存在与否的场景中具有极高的技术价值,能实现数量级的内存优化。它广泛应用于操作系统资源管理、数据库快速查询、网络过滤及算法优化等工程实践领域。本文以C++动态位图实现为例,深入剖析了其底层存储结构选择、关键位运算操作(如设置、清除、检查位)的实现细节,并探讨了内存分配、边界检查及常见问题排查等实战要点,为处理海量数据去重、排序等问题提供了高效的解

weixin_34005090的博客 346

C++_BitMap(位图)

位图的概念 数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。 位图,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。 位图的实现 class BitSet { public: BitSet(size_t range) ...

hello呀! 1630

C++位图(Bitmap)实现:海量数据高效存储与查询的核心技术

位图(Bitmap)是一种利用二进制位(bit)来紧凑表示数据状态的基础数据结构,其核心原理是将每个独立的状态映射到一个二进制位上,用0/1表示存在与否或真/假。这种设计通过极高的信息密度,将传统bool数组的内存占用降低至1/8,并利用CPU缓存和位运算指令(如按位与、或、非)实现高速的批量查询与集合运算。其技术价值在于以极低的内存开销支撑海量数据的快速存在性判断和状态管理,是构建高性能系统的基石。在应用场景上,位图技术广泛应用于Redis的SETBIT/GETBIT命令、Linux内核的页缓存与inod

weixin_32864847的博客 280

C++ BYTE保存为8位BMP/bitmap位图

该内容主要涉及位图文件结构以及位图存储时的四字节对齐两个重点。两个重点之后给出BYTE数组保存为8位位图的c++ code。 如想直接查阅代码可以跳过1、2部分,直接查看第3部分。 本文主要参照如下五个博客,将内容综合整理以备查阅。 1)位图格式分析:https://blog.youkuaiyun.com/aidem_brown/article/details/80500637 https://blog.youkuaiyun.com/qq_31094099/ar...

u013972657的博客 4738

BitMap(位图)结构的C++实现

简介位图是一种非常常见的结构,它使用每个二进制位来存放一个值的状态,正因为这个性质,它经常被用在数据压缩或者是索引等方面。有这样一道题:给40亿个不重复的无符号整数,没有经过排序,然后再给一个树,如何快速判断这个数是否在40亿个数之中?在这里如果我们实打实的存放40亿个数据在内存中,那会占据将近15个G的内存,普通电脑根本无法满足,更不用说在对其进行查找操作了。 那么如果选择位图来存储的话我们只需

MBuger的博客 2620

c/c++ 数据结构之位图(bitmap)具体解释

1.  概述 位图(bitmap)是一种很经常使用的结构,在索引。数据压缩等方面有广泛应用。本文介绍了位图的实现方法及其应用场景。 2. 位图实现 (1)自己实现 在位图中。每一个元素为“0”或“1”,表示其相应的元素不存在或者存在。 #define INT_BITS sizeof(int) #define SHIFT 5 // 2^5=32 #def...

weixin_33826268的博客 857
上一篇: C++哈希link
下一篇: C++布隆过滤器,哈希切割
chen_ever
博客等级 码龄4年 497粉丝 78原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值