【C++】哈希-bitset位图与模拟

news2025/3/3 18:23:28

目录

1.位图

1.1什么是位图 

1.2位图的作用 

 2.bitset应用

 2.1bitset构造

2.2bitset成员函数与使用 

3.bitset模拟实现 

构造函数 

set

 reset

 test

flip

count 

size 

 none,any


1.位图

在前文中我们介绍了哈希的一些内容,接下来我们介绍一个新奇的玩意,位图。 

1.1什么是位图 

  • 位图其实就是哈希的变形,同样通过映射来处理数据。
  • 位图本身并不存储数据,而是存储标记通过一个比特位来标记这个数据是否存在,1代表存在,0代表不存在。
  • 位图通常情况下用在数据量庞大,且数据不重复的情景下判断某个数据是否存在。

相比通过上面的介绍,各位还是不知道位图有啥作用。接下来我们说一下位图的作用。

1.2位图的作用 

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

1整数=4字节=32bit。

40亿个整数 = 160亿个字节
而1GB = 1024MB
1024MB = 1024 * 1024KB
1024 * 1024KB = 1024 * 1024 * 1024B(yte )≈ 10亿字节
综上1GB ≈ 10亿字节
   16GB ≈ 160亿字节

遍历时间复杂度O(N);排序(O(NlogN))利用二分查找: logN;这两种方式除了效率不够高,还有个问题是内存无法完全同时加载40亿个整数需要的16G大小空间。

我们也可以用set容器,但是底层的红黑树存放这么多数据也吃不消所以我们用位图来解决这个问题。

1个整形是32bit位,就比如整数在计算机中以二进制来存储的。而这32个位置上只有0或1,那我们可以让1表示有数据,0表示没存放数据。我们以32比特位表示一个单元。

如果采用这种方法,只需占500M内存就可以:

1G = 2^30Byte ≈ 10亿字节
(2^32 - 1)Byte ≈ 40亿字节 ≈ 4G
1Byte = 8bit
(2^32 - 1)bit = 4G/8 ≈ 500MB

例如:int a[]={2,5,7,19,24,30}
 

 2.bitset应用

 2.1bitset构造

 位图构造有三种形式,这里我们直接上代码。

void testbitset1()
{
    //1.创建一个16位位图,初始0
	std::bitset<16> foo;  // 创建一个16位位图
    //2.赋值16进制
	std::bitset<16> bar(0xfa2);   //16进制 4002
   //3.用0,1赋值或者string
	std::bitset<16> baz(std::string("0101111001"));
	std::bitset<16> bs1("011010001");
	//foo : 0000000000000000
	//bar : 0000111110100010   4002
	//baz : 0000000101111001
	//bs1 : 0000000011010001
	std::cout << "foo: " << foo << '\n';
	std::cout << "bar: " << bar << '\n';
	std::cout << "baz: " << baz << '\n';
	std::cout << "bs1: " << bs1 << '\n';
}

2.2bitset成员函数与使用 

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

 

void testbitset2()
{
	std::bitset<16> bs1;
	bs1.set(2);  //0000000000000100
	cout << bs1 << endl;
	bs1.set(4);
	bs1.set(5);  //0000000000110100
	cout << bs1 << endl;
	//获取指定位置的状态
	cout << bs1.test(5) << endl;  //位置5的状态是1
	cout << bs1.test(10) << endl; //位置10的状态是0
	//反转
	cout << bs1.flip(4) << endl;   //反转第4位
	cout << bs1.flip() << endl;    //反转所有位
	//清空
	cout << bs1.reset(10) << endl;   //清空第10位
	cout << bs1.reset()<<endl;       //全清
	//设置
	cout <<bs1.set(1)<<endl;    // 设置第一位
	cout << bs1.all() << endl;
}

bitset运算符那个就不讲了。我们直接模拟实现一下。

3.bitset模拟实现 

  • 模拟bitset就是用一个普通的数组来存储数据以达到模拟的目的。
  • 一个单元我们分成4个小组,每个小组8个位置。存放一个数据要先判断在那个单元,然后是那个小组,那个位置。
  • 找到对应单元后,数据/8=对应小组;数据%8=对应位置。
  • 如果我们以一个整型作为比特位的容器,那么如果要求0~N范围的比特位,就需要有N/32+1 个整型来容纳这些比特位,同理如果以char为容器,则需要N/8+1个char来容纳N个比特位。这里我们用vector数组作为底层容纳比特位的容器。之所以+1是怕开的空间存不下,所以多开一个,就算剩下也剩不了多少。
namespace cpp
{
	//N个比特位的位图
	template<size_t N>
	class bitset
	{
	public:
		//构造函数
		bitset();
		//把value映射的位标记成1
		void set(size_t value);
		//把value映射的位标记成0
		void reset(size_t value);
		//判断指定位value的状态是否为1
		bool test(size_t value);
		//翻转指定位置
		void flip(size_t value);
		//获取位图中可以容纳位N的个数
		size_t size()
		//统计set中1的位数
		size_t count();
		//判断所有比特位若无置为1,返回true
		bool none();
		//判断位图中是否有位被置为1,若有则返回true
		bool any();
		//全部NUM个bit位被set返回true
		bool all();
	private:
		vector<char> _bits;//位图
	};
}

这里我们用的存储类型是char。

构造函数 

 构造还是构造,但是文章已不是当年的文章了。

public :
		//构造函数
		bit_set
		{
			_bits.resize(N / 8 + 1,0);   // 全部赋值0
		}

之所以+1是因为如果数据的个数不是8的倍数时,可以再存进去,要不那多余的数据咋弄?

set

 把映射的位置标记为1(把设置位置标记为1)。

例如:value=13;

//映射的位置标为1
		void set(size_t value)
		{
			size_t i = value / 8;  //找到小组
			size_t j = value % 8;   //找到位置
			//把对应位置标记为1
			_bits[i] |= 1 << j;     //或运算,有1则1
		}

 reset

清空指定位或所有位 

这个和set正好相反,这个是把指定位置的数变成0,最后一步变化,其他不变,先按位取反,在按位与即可。j<<1按位取反后变成1,在按位与_bits[i]后就设置成0了。

//把value映射的位标记成0
		void reset(size_t value)
		{
			size_t i = value / 8;  //找到小组
			size_t j = value % 8;   //找到位置
			//把对应位置标记为1
			_bits[i] &=~(( 1 << j));     //先按位取反在与运算
		}

 test

 判断指定位置是否为1

这个跟上面的reset就缺少一个按位取反。只进行一个按位与运算即可

//判断指定位value的状态是否为1
		bool test(size_t value)
		{
			size_t i = value / 8;  //找到小组
			size_t j = value % 8;   //找到位置
			//把对应位置标记为1
			_bits[i] &= (1 << j);  
		}

flip

指定位置数据翻转: 如果是1变成0,0变成1。

这个按位异或就行了 ,相同为0,1变成0,相异为1,0^1=1

//翻转指定pos
		void flip(size_t value)
		{
			size_t i = value / 8;  //找到小组
			size_t j = value % 8;   //找到位置
			//把对应位置标记为1
			_bits[i] ^= (1 << j);
		}

count 

统计位图中出现的1的次数 

这个跟前面几个就不一样了。

这个是n&n-1

 

size_t count()
		{
			size_t count = 0;
			for (auto e : _bits)
			{
				int n = e;   //再设置个中间变量,别直接用e
				while (n)
				{
					n = n & (n - 1);
					count++;
				}
			}
			return count;
		}

size 

size的作用是获取位图中可以容纳位N的个数

size_t size()
		{
			return N;
		}

 none,any

none是查找位图中是否全部是0,是就返回true,不是返回false。

any是查找位图中是否有1,是就返回true,没有返回false。any可以复用none。完整

        bool none()
		{
			//遍历每个char
			for (auto e : _bits)
			{
				if (e != 0)//位图中有位置被置为1,返回false
					return false;
			}
			return true;//说明全为0,返回true
		}
		//若有位置为1,返回true
		bool any()
		{
			 return !none;
		}

 完整代码可到gitee查看

C++ 进阶: 本仓库存放一些较难C++代码https://gitee.com/j-jun-jie/c---advanced.git

 

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

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

相关文章

回归问题原理

回归问题是一种常见的监督机器学习任务&#xff0c;在很多领域均有广泛应用。其典型应用包括销量预测、库存预测、股票价格预测、天气预测等。本问将讨论线性回归&#xff0c;包括线性回归模型的目标函数&#xff08;损失函数和正则函数&#xff09;、线性回归模型的优化求解、…

【一包通刷】晶晨S905L3A/B_完美AI语音线刷包_打开ADB_ROOT权限

【9.0一包通刷】晶晨S905L3A/B_完美AI语音线刷包_默认打开ADB ROOT权限支持游戏启动_万物互联启动动画 适用型号&#xff1a;M401A、CM311-1a、CM311-1sa、B863AV3.1-M2、B863AV3.2-M、UNT403A、M411A等等&#xff1b; 系统版本&#xff1a;Android9 系统桌面&#xff1a;超…

【机器学习项目实战10例】(五):基于随机森林的假新闻检测项目

💥 项目专栏:【机器学习项目实战10例】 文章目录 一、基于随机森林的假新闻检测项目二、数据集介绍三、导包四、加载数据集五、划分训练集、测试集六、构建模型七、精度测试八、网格搜索一、基于随机森林的假新闻检测项目 在当今时代,传播错误信息已经成为一个真正的问题,…

初试hashlib加密模块

文章目录 一、加密解密基础二、使用hashlib模块实现数据加密(一)加密数据1、编写程序,实现功能2、运行程序,查看结果(二)登录加密校验1、编写程序,实现功能2、运行程序,查看结果一、加密解密基础 二、使用hashlib模块实现数据加密 (一)加密数据 1、编写程序,实现功…

【DeepLearning 8】Self-Attention自注意力神经网络

&#x1f34a;本文主要介绍了Self-Attention产生的背景以及解析了具体的网络模型 一、Introduction 很多时候&#xff0c;我们需要输入的数据非常的复杂&#xff0c;难以用统一、固定长度的向量来表示。比如NLP中长短不一的句子。此外&#xff0c;我们需要输出的数据有时候也会…

Spring Security中文文档

Spring Security中文文档 来源&#xff1a;https://www.springcloud.cc/spring-security.html#overall-architecture 作者 Ben Alex&#xff0c;Luke Taylor&#xff0c;Rob Winch&#xff0c;Gunnar Hillert&#xff0c;Joe Grandja&#xff0c;Jay Bryant5.1.2.RELEASE…

使用Redis查询数据库数据增加访问速度小案例

黑马B栈网课案例 文章目录案例需求&#xff1a;SQL建表所需jar包项目结构代码展示index.html首页面domainProcince.javadaoProvinceDaoProvinceDaoImplserviceProvinceServiceProvinceServiceImplservletJDBC工具类配置文件jedis.propertiesdruid.properties案例需求&#xff1…

JSP学习日记

JSP简述 Java Sever Pages----->Java服务器界面 用于前后端结合 jsp为什么淘汰&#xff1f; 由于JSP的前后端耦合性极高&#xff0c;编写代码非常臃肿。前后端的代码放在一起&#xff0c;所以JSP可以看成是已经被淘汰的技术。 为什么还要学jsp&#xff1f; 由于一些公司…

大数据:HDFS的Shell常用命令操作

文章目录一 HDFS的Shell介绍二 HDFS常用命令操作01 创建目录&#xff08;1&#xff09;创建单层目录&#xff08;3&#xff09;创建多层目录02 查看目录03 上传本地文件到HDFS04 查看文件内容05 下载HDFS文件到本地06 删除HDFS文件07 删除HDFS目录08 移动目录或文件09 文件合并…

数据库大咖,带你深入高性能MySQL架构系统,值得一看

MySQL 作为互联网中非常热门的数据库&#xff0c;在高并发业务场景下&#xff0c;一条好的 MySQL 语句能为企业节省大量的运作时间和成本&#xff0c;这也是为何互联网大厂面试官最爱考察数据库底层和性能调优的原因。因此&#xff0c;了解其底层原理和架构的设计非常重要&…

Go-Excelize API源码阅读(三十五)——SetSheetCol

Go-Excelize API源码阅读&#xff08;三十五&#xff09;——SetSheetCol 开源摘星计划&#xff08;WeOpen Star&#xff09; 是由腾源会 2022 年推出的全新项目&#xff0c;旨在为开源人提供成长激励&#xff0c;为开源项目提供成长支持&#xff0c;助力开发者更好地了解开源…

【C++数据结构】程序性能分析

程序性能分析 2.1 什么是程序性能 程序性能&#xff1a;所谓程序性能&#xff08;performance of a program&#xff09;是指运行这个程序所需要的内存和时间的多少。 性能分析&#xff1a;在性能分析&#xff08;performance analysis&#xff09;时&#xff0c;采用分析方…

ceph命令应用

记录&#xff1a;337 场景&#xff1a;在CentOS 7.9操作系统上&#xff0c;在ceph集群中&#xff0c;使用ceph命令查看ceph集群信息&#xff0c;以及mon、mgr、mds、osd、rgw等组件信息。 版本&#xff1a; 操作系统&#xff1a;CentOS 7.9 ceph版本&#xff1a;ceph-13.2.…

JavaSE从基础到入门:抽象类和接口

1.抽象类 1.抽象类的概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类。 比如&#x…

Android App开发实战项目之仿喜马拉雅的听说书App实现(超详细 附源码)

需要全部源码请点赞关注收藏后评论区留下QQ~~~ 一、需求分析 用户不仅能在平台上收听音频&#xff0c;还能成为内容创作者&#xff0c;总之长音频分享平台需要满足两种角色的使用&#xff1a;一种是作为内容创作者发布自己的音频&#xff0c;另一种是作为用户欣赏平台上的已有…

java项目-第162期ssm电影售票系统_ssm毕业设计_计算机毕业设计

java项目-第162期ssm电影售票系统_ssm毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm电影售票系统》 该项目分为2个角色&#xff0c;管理员、用户。 用户可以浏览前台电影信息、新片预告&#xff0c;并且可以进行影片预订、 座位选座。用户登录后台…

谈数据库查询涉及的存储效率

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 参考&#xff1a;https://blog.csdn.net/Sword52888/article/details/125352635 11月马上也进入尾声了&#xff1b;紧接着的12月&#xff0c;新年也就不远了… 今年对数据查询做了许多的分析、测试、修改、验证&#xf…

centOS 7 Install Harbor(私有镜像仓库)V2

一、安装docker环境 略. 二、下载离线安装包 下载地址https://github.com/goharbor/harbor/releases/download/v1.10.15/harbor-offline-installer-v1.10.15.tgz三、拷贝到服务器/application #解压 tar -xvf harbor-online-installer-v1.2.0.tgz #生成证书 cd /applicati…

【计算机毕业设计】45.医院挂号系统

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 伴随着社会以及科学技术的发展&#xff0c;互联网已经渗透在人们的身边&#xff0c;网络慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;管理系统这一名词已不陌生&…

【计算机毕业设计】41.航空订票系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把航空订票与现在网络相结合&#xff0c;利用JSP技术建设航空订票系统&#xff0c;实现航空订票的信息化。则对于进一步提高航班公司的发展&#xff0c;丰富航空订票经验能起到不少的促进作用。 航空订票系统能够通过互联网…