位图,位运算符

位图的概念

所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。


常见位图的应用:

快速查找某个数据是否在一个集合中。
求两个集合的交集、并集等。

位运算

& 与 :有0则为0,全为1则为1

| 或:有1则为1,全为0则为0

^ 异或:相同为0,相异为1

~ 按位取反

代码

BitSet.h

#pragma once
#include<iostream>
#include<vector>
using namespace std;

namespace lrf
{
	template<unsigned int N>
	class bitset
	{
	public:
		bitset()
		{
			_a.resize(N / 32 + 1);
		}
		void set(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;
			_a[i] |= (1 << j);
		}

		void reset(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;
			_a[i] &= (~(1 << j));
		}

		bool test(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;
			return _a[i] & (1 << j);
		}
	private:
		vector<int> _a;
	};

	template<size_t N>
	class twobitset
	{
	public:
		void set(size_t x)
		{
			// 00 -> 01
			if (!_bs1.test(x) && !_bs2.test(x))
			{
				_bs2.set(x);
			} // 01 -> 10
			else if (!_bs1.test(x) && _bs2.test(x))
			{
				_bs1.set(x);
				_bs2.reset(x);
			}
			// 本身10代表出现2次及以上,就不变了
		}

		bool is_once(size_t x)
		{
			return !_bs1.test(x) && _bs2.test(x);
		}
	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};
}

test.c

#include"BitSet.h"
//
//int main()
//{
//	lrf::bitset<1000> bs;
//	bs.set(1);
//	bs.set(10);
//	bs.set(100);
//
//	cout << bs.test(1) << endl;
//	cout << bs.test(10) << endl;
//	cout << bs.test(100) << endl;
//	cout << bs.test(999) << endl<<endl;
//
//	bs.set(999);
//	bs.reset(10);
//
//	cout << bs.test(1) << endl;
//	cout << bs.test(10) << endl;
//	cout << bs.test(100) << endl;
//	cout << bs.test(999) << endl << endl;
//
//
//	lrf::bitset<-1> bs1;
//	//bit::bitset<0xffffffff> bs2;
//
//
//	return 0;
//}

//只出现一次
int main()
{
	int a[] = { 1,2,3,3,4,4,4,4,4,2,3,6,3,1,5,5,8,9};
	lrf::twobitset<10> tbs;
	for (auto e : a)
	{
		tbs.set(e);
	}

	for (auto e : a)
	{
		if (tbs.is_once(e))
		{
			cout << e << " ";
		}
	}
	cout << endl;
}

//求两个大文件中元素交集
//int main()
//{
//	int a1[] = { 1,2,3,3,4,4,4,4,4,2,3,6,3,1,5,5,8,9 };
//	int a2[] = { 8,4,8,4,1,1,1,1 };
//
//	lrf::bitset<10> bs1;
//	lrf::bitset<10> bs2;
//
//	// 去重
//	for (auto e : a1)
//	{
//		bs1.set(e);
//	}
//
//	// 去重
//	for (auto e : a2)
//	{
//		bs2.set(e);
//	}
//
//	for (int i = 0; i < 10; i++)
//	{
//		if (bs1.test(i) && bs2.test(i))
//		{
//			cout << i << " ";
//		}
//	}
//	cout << endl;
//}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值