STL之位图(bitset)

目录

  • 位图
    • bitset介绍
    • bitset使用
  • 模拟实现
  • 位图的应用——题目
  • 总结

位图

bitset介绍

STL之位图(bitset)_第1张图片

参考文档:bitset

在 C++ STL 中,std::bitset 是一个固定大小的容器类,用于表示二进制位序列。它可以被看作是一个长度固定为 N 的布尔数组,其中每个元素只有两种取值:0和1。
STL之位图(bitset)_第2张图片

bitset使用

常见应用:1.快速查找某个数据是否在集合中 2.排序+去重 3.求两个集合的交集、并集等 4.操作系统中磁盘块标记

接口:

STL之位图(bitset)_第3张图片

示例:

排序+去重

#include        // std::cout
#include          // std::string
#include         // std::size_t
#include          // std::bitset

int main ()
{
    std::bitset<5> foo (std::string("01011"));

    std::cout << "foo contains:";

    for (std::size_t i=0; i

模拟实现

代码:

template
class bitset
{
public:
	bitset()
	{
		//开辟(N/8+1)个字节空间
		_bits.resize(N / 8 + 1, 0);
	}
		
	//在第x位上置1
	void set(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;

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

	//在第x位上置0
	void reset(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;

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

	//判断x位上的值
	bool test(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;

		return _bits[i] & (1 << j);
	}
    
    //获取可以容纳的位的个数
    size_t size()
    {
        return N;
    }

private:
	vector _bits;
};

将一个整型数字x映射到位图中的具体的一个比特位。

  • 找到在第几个字节里面(以char为单位开辟的空间)
  • 找到在该字节的第几个位,并通过位操作(&、|、~)访问

以set()示例:

STL之位图(bitset)_第4张图片

使用:

void test_bit_set1()
{
    bitset<100> bs1;
    bs1.set(8);
    bs1.set(9);
    bs1.set(20);

    cout << bs1.test(8) << endl;
    cout << bs1.test(9) << endl;
    cout << bs1.test(20) << endl;

    bs1.reset(8);
    bs1.reset(9);
    bs1.reset(20);

    cout << bs1.test(8) << endl;
    cout << bs1.test(9) << endl;
    cout << bs1.test(20) << endl;
}

位图的应用——题目

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

1 G = 1024 ∗ 1024 ∗ 1024 = 2 30 ≈ 10 亿 b y t e 1G = 1024*1024*1024=2^{30}\approx10亿byte 1G=102410241024=23010亿byte

40亿个整数大约需要占用16G空间大小

使用位图的话,用对应bit位的0/1来判断某个数字是否存在。

其中按照上述代码实现的bitset的话,template,最多可以传 2 32 − 1 2^{32} - 1 2321(4294967295,42亿多)大小的数字,这最大开辟42亿多比特位的空间,其中每个比特位都可以映射到对应的数。

bool judge()
{
    bitset<-1> bs;
    //bitset<0xffffffff> bs1;
    
    //将整数映射到位图bs中
    for()
    {
        bs.set(x);
    }
    
    //判断
    bs.test(x);
}

2.给定100亿个整数,设计算法找到只出现一次的整数?

状态:0次、1次、2次及以上

思路:使用两个bitset,一个表示高位,一个表示第位。一个数就有{00, 01, 10, 11}4种表示了

template
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);
		}
		else if (inset1 == true && inset2 == false)
		{
			// ->11
			_bs1.set(x);
			_bs2.set(x);
		}
	}
	//出现一次的整数: 01
	void print_once_num()
	{
		for (size_t i = 0; i < N; ++i)
		{
			if (_bs1.test(i) == false && _bs2.test(i) == true)
			{
				cout << i << endl;
			}
		}
	}

private:
	bitset _bs1;
	bitset _bs2;
};
void test_bit_set3()
{
    int a[] = { 3, 4, 5, 2, 3, 4, 4, 4, 4, 12, 77, 65, 44, 4, 44, 99, 33, 33, 33, 6, 5, 34, 12 };

    twobitset<100> bs;
    for (auto e : a)
    {
        bs.set(e);
    }

    bs.print_once_num();
}

3.给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?

同上题,使用两个bitset,一个bitset映射一个文件,映射位都是1的值就是交集

4.位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

同上上题,使用两个位图,一个高位,一个低位。
出现0次(00)、出现1次(01)、出现2次(10)、出现3次及以上(11)。找01和10

总结

位图的特点:

  • 节省空间,快(直接定址法,不存在冲突)
  • 相对局限,只能映射处理整型

    观看~~

你可能感兴趣的:(一块来学C++,数据结构,c++,开发语言)