STL——bitset

        哈希即散列是一种数据结构的思想。而哈希表是这种思想的一种应用,除了哈希表,本文要介绍的位图以及布隆过滤器也是哈希思想的体现。

        C++的STL已经实现了位图这一种数据结构:

目录

一、概念

二、位图的实现

1.框架

2.set

3.reset

4.test

 三、位图的应用


一、概念

如果遇到下面这样的要求:

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

        很多人可能会想用map、set、哈希这样的结构存储这些数据,然后查找。或者用排序+二分查找等等思路。

        然而,真正面临的问题是:

  

        无论如何这都是不符合常理的要求。

         

        而应用哈希即散列的思想,我们的目的是判断“在/不在” 两种状态,而一个bit位的0/1值完全可以满足要求,使用bit位来存储状态,用于判断在与不在的数据结构就是位图。通常用于海量数据,数据无重复的场景。

二、位图的实现

        位图中比较重要的成员函数

set将存在的数据对应位设置为1
reset        将不存在的数据对应位设置为0
test          判断是否存在,返回值为bool类型

1.框架

    template<size_t N>
	class bitset
	{
	public:
		bitset()
		{
			_bits.resize(N / 32 + 1, 0);
		}
	private:
		vector<int> _bits;
	};

        成员变量是一个vector<int>,我们打算用整型的每一位来达到需求。

        对于这个数组开多大的空间,如果有64个数据,则用64个bit位即两个字节即可。如果有70个数据则需要多开一个字节的空间。

2.set

        //将x对应vector中的bit位改为1
        void set(size_t x)
		{
			assert(x <= N)
			{
				size_t i = x / 32;
				size_t j = x % 32;

				_bits[i] |= (1 << j);
			}
		}

         代码中:

        除32对应到第i个字节,模32对应到第i个字节的第j个比特位。而不影响其他位的情况下,要将对应比特位修改为1,需要将1左移(考虑到大小端存储,我们平常所说的左移本质是向高位移动),或运算1将比特位修改为1,对应的,与运算0将比特位修改为0。

3.reset

        //将对应位修改为0
        void reset(size_t x)
		{
			assert(x <= N);

			size_t i = x / 32;
			size_t j = x % 32;

			_bits[i] &= ~(1 << j);
		}

4.test

        bool test(size_t x)
		{
			assert(x <= N);

			size_t i = x / 32;
			size_t j = x % 32;

			return _bits[i] & (1 << j);

		}

        _bits[i]是整个字节,而我们只需要一个bit位,将一个bit位转换为一个类型只需要按位与1即可。

 三、位图的应用

现有100亿个整数,设计算法找到只出现一次的整数。

         不难知道,size_t 的最大值范围是42亿左右,100亿个整数必然有重复值。利用位图的特点,为了达到需求,某一个数,可能的状态是出现0次、出现1次、出现2次及以上,而我们关注的是它出现1次的情况,因此只需要3个bit状态即可达到需求,使用两个bit位即可。

        00 ------- 出现0次

        01 ------- 出现1次

        10 ------- 出现2次不止

    template<size_t N>
	class two_bit_set
	{
	public:
		void set(size_t x)
		{ 
			if (_bs1.test(x) == false
				&& _bs2.test(x) == false)
			{
				_bs2.set(x);
			}
			else if (_bs1.test(x) == false
				&& _bs2.test(x) == true)
			{
				_bs1.set(x);
				_bs2.reset(x);
			}
			else
			{

			}
		}
		bool test(size_t x)
		{
			if (_bs1.test(x) == false
				&& _bs2.test(x) == true)
			{
				return true;
			}
			return false;
		}
	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

现有两个文件,分别有100亿个整数,只有1G内存,如何找到它们的交集

        存放100亿个整型,大约需要40G。将这些存储下来是不现实的,一般对于大量数据的处理,用位图来处理。实际的整型数据量在42亿左右,而42亿bit的大小为512MB,因此1GB的空间用来开两个大小为512MB的位图,依次遍历两个位图,比特位同时为1的时候说明这个数据属于交集。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值