Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++位图

C++位图

原创
作者头像
梨_萍
发布于 2023-04-24 06:44:03
发布于 2023-04-24 06:44:03
4860
举报
文章被收录于专栏:梨+苹的C++梨+苹的C++

位图

代码语言:txt
AI代码解释
复制
给定40亿个不重复、没排序的无符号整数,再给一个无符号整数,如何快速判断一个数是否在这40亿个数中???

首先想到的是归并排序+二分查找。排序可以排,但是通过文件指针去查找会很慢。

其次是set和哈希表。set自动可以排序且在红黑树中查找速度也很快。但要把40亿个整数加上红黑树的节点(三叉链外加颜色)放进内存里,内存明显不够,不可取;哈希表同样是把40亿个整数外加节点放进内存里,内存明显不够,也不可取。

那么既然要把40亿个整形放进内存里,判断在或者不在,用1标记在用0标记不在。1个比特位就能满足标记1或0。用直接定址法。1个char类型-1个字节-8个比特位。无符号整数有42亿9千万个,全部用比特位来代表的话就只需要512M。这种方法可行。用char类型来开辟空间,那么第一个char就能存储0~7,第二个char就能存储8~15,第三个。。。。。。

image-20230422112358980
image-20230422112358980

set

把要set的值通过/8找到对应的char(小位图),再通过%8找到对应的位置,把该位置标记成1即为该值存在于这堆数中

代码语言:c++
AI代码解释
复制
		void Set(size_t x)//把x值对应的标记为置为1
		{
			//计算x位于哪一个char上
		//	size_t i = x / 8;
			size_t i=x >> 3;//相当于x/8
			//计算x位于哪个bit上
			size_t j = x % 8;
			_bit[i] |= (1 << j);
		}
位图set
位图set

Reset

把要Reset的值通过/8找到对应的char(小位图),再通过%8找到对应的位置,把该位置标记成0即把该值从这堆数中抹去

代码语言:c++
AI代码解释
复制
void ReSet(size_t x)//把x值对应的标记置为0
		{
			//计算x位于哪一个char上
			//size_t i = x / 8;
			size_t i = x >> 3;//相当于x/8
			//计算x位于哪个bit上
			size_t j = x % 8;
			_bit[i] &= (~(1 << j));
		}
位图reset
位图reset

Test

把要Reset的值通过/8找到对应的char(小位图),再通过%8找到对应的位置。先按位取反原来的位图,再把原来的位图与取反的位图按位与,若存在1则为非0,为真返回true;若不存在则没有1全0,为假,返回false;

代码语言:c++
AI代码解释
复制
		bool Test(size_t x)//判断x是否在这堆数里面
		{
			//计算x位于哪一个char上
			//size_t i = x / 8;
			size_t i = x >> 3;//相当于x/8
			//计算x位于哪个bit上
			size_t j = x % 8;
			return _bit[i] & (1 << j);
		}
位图test1
位图test1
位图test2
位图test2

整体代码

代码语言:c++
AI代码解释
复制
	template<size_t N>//用非类型模板参数---N为要往位图里存储多少个数
	class  BitSet
	{public:
		BitSet()
		{
            //_bit.resize(N >> 3) + 1);
			_bit.resize(N / 8 + 1);//多开一个
		}

		void Set(size_t x)//把x值对应的标记为置为1
		{
			//计算x位于哪一个char上
		//	size_t i = x / 8;
			size_t i=x >> 3;//相当于x/8
			//计算x位于哪个bit上
			size_t j = x % 8;
			_bit[i] |= (1 << j);
		}

		void ReSet(size_t x)//把x值对应的标记置为0
		{
			//计算x位于哪一个char上
			//size_t i = x / 8;
			size_t i = x >> 3;//相当于x/8
			//计算x位于哪个bit上
			size_t j = x % 8;
			_bit[i] &= (~(1 << j));
		}

		bool Test(size_t x)//判断x是否在这堆数里面
		{
			//计算x位于哪一个char上
			//size_t i = x / 8;
			size_t i = x >> 3;//相当于x/8
			//计算x位于哪个bit上
			size_t j = x % 8;
			return _bit[i] & (1 << j);
		}

		vector<char> _bit;
	};

当开最大的整形数时,内存也只占512M左右

image-20230423160349779
image-20230423160349779

库里面也有

bitset

image-20230423160904693
image-20230423160904693

位图应用

  1. 快速查找某个数据是否在一个集合中
  2. 排序+去重
  3. 求两个集合的交集、并集等
  4. 操作系统中磁盘块标记
代码语言:txt
AI代码解释
复制
给两个文件,分别有100亿个整数,我只有1G内存,如何找到两个文件的交集???

把文件1的数据放进位图1,把文件2的数据放进位图2,然后逐个遍历位图1的数据同时遍历位图2。当两个位图的数据的标记位都是1时,说明该数据即存在文件1也存在文件2,这个数据就是两个文件的交集。逐个遍历两个位图,找出相同的数据即可。

image-20230423183904153
image-20230423183904153
代码语言:c++
AI代码解释
复制
//测试
void testBitset()
	{
		BitSet<100> bs1;
		BitSet<100> bs2;
		int path1[] = { 1,2,3,4,5 };
		int path2[] = { 1,3,5 };

		for (auto e : path1)
		{
			bs1.Set(e);
		}

		for (auto e : path2)
		{
			bs2.Set(e);
		}

		for (size_t i = 0; i < 100; i++)
		{
			if (bs1.Test(i) && bs2.Test(i))//11
			{
				cout << i << endl;
			}
		}
		}
代码语言:txt
AI代码解释
复制
一个文件有100亿个int,1G内存,设计算法找出次数不超过2次的所有整数

用两个位图来记录出现的数据次数。出现0次就是00,出现1次就是01,出现2次就是10,出现3次或以上就是11。记录两个位图标记位为01,10的数据。

浅搓了个代码

代码语言:c++
AI代码解释
复制
template<size_t N>
	class twoBitset
	{
	public:
		void Set(size_t x)
		{

			if (!bs1.Test(x) && !bs2.Test(x))//两个位图都是0---数据出现0次
			{//00->01
				bs2.Set(x);
			}
			else if (!bs1.Test(x) && bs2.Test(x))//第一个位图是1,第二个位图是0---数据出现1次
			{//01->10
				bs1.Set(x);
				bs2.ReSet(x);
			}
			else //两个位图都是1---数据出现2次
			{//10->11
				
				bs2.Set(x);
			}
			//else//出现3次及以上
			//{
			//	break;
			//}
		}

		void  Printones()
		{
			for (size_t i = 0; i < N; i++)
			{
				if (!bs1.Test(i) && bs2.Test(i))//01
				{
					cout << i << endl;
				}
				else if (bs1.Test(i) && !bs2.Test(i))//10
				{
					cout  << i << endl;
				}
				


			}

		}
	private:
		BitSet<N> bs1;
		BitSet<N> bs2;

	};
代码语言:txt
AI代码解释
复制
给一个超过100G的log file,log中存着IP地址,设计算法找到出现次数最多的IP地址

先通过哈希函数哈希切分这个100G的文件,然后冲突的IP地址放进同一个小文件里;接着用map依次统计每个文件的相同IP的次数,统计完一个clear掉map统计下一个。

此时小文件有两种情况,一是小文件里大部分冲突的IP都是重复的,此时直接用map可以统计次数。二是小文件里大部分冲突的IP都是不重复的,此时用map统计不下,使用mp的insert时会插入失败,即没内存去new节点了,new失败会抛异常,这时需要换个哈希函数,对这个小文件再次通过哈希切分,分成更细小的文件。

image-20230423213026093
image-20230423213026093

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(3)(布隆过滤器和位图)
bitset 是 C++ 标准库中的一个类模板,主要用于管理固定大小的位集合。它能够在一个单一的对象中存储多个二进制位,非常适合用于需要高效存储和快速访问位信息的场景。
hope kc
2024/10/24
1440
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(3)(布隆过滤器和位图)
C++ 哈希的应用【位图】
位图(bitset)是一种特殊的数据结构,仅仅依靠 0、1 表示当前位置是否有数据存在,常用于对查找速度和存储空间有着高要求的场景中,除此之外,位图还可以配合宏定义,实现同时传递多个参数,比如系统调用 open,其中的参数2(打开方式)就是一个简单的位图结构
北 海
2023/07/28
3280
C++ 哈希的应用【位图】
【C++高阶】哈希—— 位图 | 布隆过滤器 | 哈希切分
之前我们已经在这篇文章中 【C++高阶】哈希函数底层原理全面探索和深度解析-CSDN博客
IsLand1314
2024/10/15
1670
【C++高阶】哈希—— 位图 | 布隆过滤器 | 哈希切分
【C++进阶】位图/布隆过滤器与海量数据处理
我们知道数据的最小存储位是比特(bite),每个比特位只能是0或1,我们用1和0来表示在或不在,或是其它类型的状态信息,这种结构称作位图。
aosei
2024/01/23
1620
【C++进阶】位图/布隆过滤器与海量数据处理
【C++】哈希应用:位图 哈希切分 布隆过滤器
1. 大厂经典的面试题,给你40亿个不重复的无符号整数,让你快速判断一个数是否在这40亿个数中,最直接的思路就是遍历这40亿个整数,逐一进行比对,当然这种方式可以倒是可以,但是效率未免太低了。 另一种方式就是排序+二分的查找,因为二分查找的效率还是比较高的,logN的时间复杂度,但是磁盘上面无法进行排序,排序要支持下标的随机访问,这40亿个整数又无法加载到内存里面,你怎么进行排序呢?所以这样的方式也是不可行的。 那能不能用红黑树或者哈希表呢?红黑树查找的效率是logN,哈希表可以直接映射,查找的效率接近常数次,虽然他们查找的效率确实很快,但是40亿个整数,那就是160亿字节,10亿字节是1GB,16GB字节红黑树和哈希表怎么能存的下呢?这还没有算红黑树的三叉链结构,每个结点有三个指针,而且哈希表每个结点会有一个next指针,算上这些的话需要的内存会更大,所以用红黑树或哈希表也是无法解决问题的。
举杯邀明月
2023/04/12
6320
【C++】哈希应用:位图 哈希切分 布隆过滤器
【C++修炼之路】24.哈希应用--位图
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。
每天都要进步呀
2023/03/28
2710
【C++修炼之路】24.哈希应用--位图
【数据结构】哈希经典应用:位图——[深度解析](8)
YY的秘密代码小屋
2024/01/23
3160
【数据结构】哈希经典应用:位图——[深度解析](8)
【C++】位图应用 | 布隆过滤器
给40亿个不重复的无符号整数,没排过序,给一个无符号整数,如何快速判断一个数是否在这40亿个数中
lovevivi
2023/10/17
2050
【C++】位图应用 | 布隆过滤器
位图/布隆过滤器/海量数据处理方式
所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。
二肥是只大懒蓝猫
2023/03/30
3960
位图/布隆过滤器/海量数据处理方式
【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
YY的秘密代码小屋
2024/01/23
1720
【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
【C++从小白到大牛】位图讲解
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。【腾讯】
用户11316056
2024/10/16
1070
【C++从小白到大牛】位图讲解
哈希应用
所谓位图,就是用每一个比特位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的
芝士就是菜
2023/04/20
4370
哈希应用
极致高效的数据处理:位图、布隆过滤器与哈希切分的奇妙之旅
本文将带领你深入探索哈希的三大高效应用——位图、布隆过滤器和哈希切分。它们如同精巧的齿轮,共同驱动着现代计算系统的高效运作。从减少存储空间到加速查找效率,从数据去重到流式处理,这些技术在幕后悄然发挥着巨大的力量。让我们一起揭开哈希算法的神秘面纱,领略数据处理的艺术之美。
suye
2024/11/19
1940
极致高效的数据处理:位图、布隆过滤器与哈希切分的奇妙之旅
C++:哈希拓展-位图
第二种方法就是先排序+二分查找:肯呢个有些人会觉得,排序的代价太大了;其实不然,我们只需要排序一次那么接下来的查找就好办了; 对于二分查找,效率是O(logn),根据2^10=1024,那2^30的数量级就是10^9,就已经上升到亿了,2^32大约就是40亿;所以我们使用二分在40亿个数中查找一个数最多只需要查找32次就可以了,效率是相当客观的;
啊QQQQQ
2024/11/19
580
C++:哈希拓展-位图
位图与布隆过滤器
此篇文章针对大量数据进行筛选或者判断重复,存在等一系列侧重于在特定空间,时间等允许范围内进行选择的问题提出解决方案。
羑悻的小杀马特.
2025/01/23
1000
位图与布隆过滤器
【C++】哈希(位图,布隆过滤器)
给 40亿个不重复的无符号整数, 没排过序。给一个无符号整数,如何快速判断一个数是否在
The sky
2023/04/12
3230
【C++】哈希(位图,布隆过滤器)
C++语法中bitset位图介绍及模拟实现
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。
芯动大师
2023/10/14
2760
C++语法中bitset位图介绍及模拟实现
【C++】STL --- 哈希
在 C++98 中,STL 提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 O(logN),即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到,因此在 C++11 中,STL 又提供了4个 unordered 系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同,本文中只对 unordered_map 和 unordered_set 进行介绍,unordered_multimap 和 unordered_multiset 大家可以查看文档介绍 - - - unordered_multimap / unordered_multiset.
YoungMLet
2024/03/01
1890
【C++】STL --- 哈希
【C++航海王:追寻罗杰的编程之路】哈希的应用——位图 | 布隆过滤器
位图的概念:所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据是否存在的。
枫叶丹
2024/07/15
1280
【C++航海王:追寻罗杰的编程之路】哈希的应用——位图 | 布隆过滤器
C++:位图和布隆过滤器
问题:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在 这40亿个数中。【腾讯】
小陈在拼命
2024/05/10
1260
C++:位图和布隆过滤器
相关推荐
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(3)(布隆过滤器和位图)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档