【C++】位图解决海量数据,判断某数是否存在问题

场景

现有40亿个不重复无符号整数,未排序。在其中检测一个给定无符号整数是否存在。

40亿数据总字节大小大概为15G,无法一次加载入内存中

尝试方法:
  1. 遍历 --------时间复杂度O(N)
  2. 先排序 O(NlogN),再二分查找:O(logN)
  3. 哈希切割-------查找效率不高
  4. 使用位图解决-----查找效率最高,最省空间
位图解决的思路

数据是否保存在40亿条数据当中,有存在/不存在两种状态,可以使用二进制1/0在比特位中进行标记。
40亿条数据为无符号整形,其最大取值范围为0到0xffffffff(2^23个无符号整形数据),若每个数字对应一个比特位,则只需要512兆存储空间,大大节省了查找时占用的空间资源。

我们可以通过C++中的bitset类来实现

#include<bitset>
size_t array[] = { 1, 6, 40, 23, 11, 12, 13 };
	std::bitset<512> bt;//<给出的比特位数> 512*2^20
	for (auto e : array){ //将数组中数据遍历统计,相应比特位置1
		bt.set(e);
	}
	std::cout << "count: " << bt.count() << std::endl;//打印比特位为1位的总数

	if (bt.test(6))//查找6是否存在(6所在的对应比特位是否为1)
		std::cout << "6 can find" << std::endl;
	bt.reset(23);//删除23

也可以自己模拟bitset来实现,理解位图思想
自定义的bitset类中,给定两个成员变量,一个是char类型的数组 _bit 用于保存每个无符号整数是否存在,_bit中一个元素占8个比特位。在保存数据data时,data除8代表在的数组的第几个元素,data模8代表其在该元素比特位的第几位。
在这里插入图片描述

//自定义的位操作
namespace mybitset
{
	template <size_t N> //N为位数
	class bitset{
	public:
		bitset()
			:_bit(N/8+1)
		{}
		//比特位为1的总数
		size_t count(){
			return _count;
		}
		//比特位总数
		size_t size(){ 
			return N;
		}
		//将pos位置置1
		void set(size_t pos){
			assert(pos < N);
			size_t _byte = pos / 8; //哪个字节
			size_t bit = pos % 8; //哪个比特位

			_bit[_byte] |= (1 << bit); //1向左移bit位
			_count++;
		}

		//将pos位置置0
		void reset(size_t pos){
			assert(pos < N);
			size_t _byte = pos / 8; //哪个字节
			size_t bit = pos % 8; //哪个比特位
											//1100 1010
											//0000 1000  1左移bit位
			_bit[_byte] &= (~(1 << bit));   //1111 0111  取反
			_count--;
		}

		//检测pos位置比特位是否为1
		bool test(size_t pos){
			assert(pos < N);
			size_t _byte = pos / 8; //哪个字节
			size_t bit = pos % 8; //哪个比特位
											//1100 1010
			if (_bit[_byte] &= (1 << bit)){ //0000 1000 
				return true;
			}
			return false;
		}

	private:
		std::vector<char> _bit; //一个char占一个字节(8个比特位)
		size_t _count; //比特位为1的总数
	};
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值