~位图(补充)~

       上一篇博客中讲到的位图只能判断数据是否存在,但并不能判断该数据是只存在1个还是存在多个,这就是一个小小的缺陷!没事,稍改代码就可以弥补这一缺陷。

 

       方便实现代码,我们假设数组的数据类型为int,则位图所实现的接口如下:

0.初始化数组

  设数据的范围为range,开辟一个大小为(range>>4)+1的数组,并使其初始化为0。

BitSet(size_t range)
{
	_set.resize((range >> 4) + 1, 0);
}

1.确定数据应存入的位置

  设要存入的数据为num,index表示的是存入数组的哪个数据中,pos表示的是存入数据的哪位二进制位中。

size_t index = num >> 5;
size_t pos = (num % 16) * 2;

2.设置数据

  用2位二进制位表示一个数据,其中00表示数据不存在,01表示只存在1个,11表示数据存在多个。

void set(size_t num)
{
	size_t index = num >> 5;
	size_t pos = (num % 16) * 2;

	if((_set[index] & (1 << pos)) == 0)
	{
		_set[index] |= (1 << pos);
	}
	else
	{
		_set[index] |= (1 << pos);
		++pos;
		_set[index] |= (1 << pos);
	}
}

3.清除数据

  该自定义类不能设计清除数据这一接口,因为在清除数据时,若数据存在时无法判断数据是存在1个还是多个。

4.判断数据是否存在

   若输出为0表示数据不存在,输出为1表示数据存在1个,输出为2表示数据存在多个。

int Test(size_t num)
{
	size_t index = num >> 5;
	size_t pos = (num % 16) * 2;

	if((_set[index] & (1 << pos)) == 0)
	{
		return 0;
	}
	else if((_set[index] & (1 << pos)) && (_set[index] & (1 << (++pos))) == 0)
	{
		return 1;
	}
	else
	{
		return 2;
	}
}

 

完整的源代码及测试用例如下:

#include <vector>

class BitSet
{
public:
	BitSet(size_t range)
	{
		_set.resize((range >> 4) + 1, 0);
	}

	void set(size_t num)
	{
		size_t index = num >> 5;
		size_t pos = (num % 16) * 2;

		if((_set[index] & (1 << pos)) == 0)
		{
			_set[index] |= (1 << pos);
		}
		else
		{
			_set[index] |= (1 << pos);
			++pos;
			_set[index] |= (1 << pos);
		}
	}

	int Test(size_t num)
	{
		size_t index = num >> 5;
		size_t pos = (num % 16) * 2;

		if((_set[index] & (1 << pos)) == 0)
		{
			return 0;
		}
		else if((_set[index] & (1 << pos)) && (_set[index] & (1 << (++pos))) == 0)
		{
			return 1;
		}
		else
		{
			return 2;
		}
	}
protected:
	vector<int> _set;
};

void TestBitSet()
{
	BitSet s(1000);
	s.set(1);
	s.set(1);
	s.set(8);
	cout<<s.Test(1)<<endl;
	cout<<s.Test(8)<<endl;
	cout<<s.Test(33)<<endl;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值