位图总结


参考:
https://blog.csdn.net/v_july_v/article/details/6685962

位图

https://blog.csdn.net/ArchyLi/article/details/78573362
位图BitMap:位图是一个数组,数组中的每一个数据元素的每一个二进制位表示一个数据,0表示数据不存在,1表示数据存在。
在这里插入图片描述

如上所示,当我们需要存放一个数据的时候,我们需要安装以下方法:

  1. 首先确定这个数字在整个数据的哪一个数据(区间)。
  2. 确定这个数据(区间)的哪一个Bit位上。
  3. 在这个位上置1即可。
  • 举例
    假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复)。那么我们就可以采用Bit-map的方法来达到排序的目的。要表示8个数,我们就只需要8个Bit(1Bytes),首先我们开辟1Byte的空间,将这些空间的所有Bit位都置为0(如下图:)
    在这里插入图片描述
    然后遍历这5个元素,首先第一个元素是4,那么就把4对应的位置为1(可以这样操作 p+(i/8)|(0×01<<(i%8)) 当然了这里的操作涉及到Big-ending和Little-ending的情况,这里默认为Big-ending),因为是从零开始的,所以要把第五位置为一(如下图):
    在这里插入图片描述
    然后再处理第二个元素7,将第八位置为1,,接着再处理第三个元素,一直到最后处理完所有的元素,将相应的位置为1,这时候的内存的Bit位的状态如下:
    在这里插入图片描述
    然后我们现在遍历一遍Bit区域,将该位是一的位的编号输出(2,3,4,5,7),这样就达到了排序的目的。下面的代码给出了一个BitMap的用法:排序。
//定义每个Byte中有8个Bit位
#include <memory.h>
#define BYTESIZE 8
void SetBit(char *p, int posi)
{
	for(int i=0; i < (posi/BYTESIZE); i++)
	{
		p++;
	}
	*p = *p|(0x01<<(posi%BYTESIZE));//将该Bit位赋值1
    return;
}

 
void BitMapSortDemo()
{
	//为了简单起见,我们不考虑负数
	int num[] = {3,5,2,10,6,12,8,14,9};
	//BufferLen这个值是根据待排序的数据中最大值确定的
	//待排序中的最大值是14,因此只需要2个Bytes(16个Bit)
	//就可以了。
	const int BufferLen = 2;
	char *pBuffer = new char[BufferLen];
	//要将所有的Bit位置为0,否则结果不可预知。
	memset(pBuffer,0,BufferLen);
	for(int i=0;i<9;i++)
	{
		//首先将相应Bit位上置为1
		SetBit(pBuffer,num[i]);
	}

 	//输出排序结果
	for(int i=0;i<BufferLen;i++)//每次处理一个字节(Byte)
	{
		for(int j=0;j<BYTESIZE;j++)//处理该字节中的每个Bit位
		{
			//判断该位上是否是1,进行输出,这里的判断比较笨。
			//首先得到该第j位的掩码(0x01<<j),将内存区中的
			//位和此掩码作与操作。最后判断掩码是否和处理后的
			//结果相同
			if((*pBuffer&(0x01<<j)) == (0x01<<j))
			{
				printf("%d ",i*BYTESIZE + j);
			}
		}
		pBuffer++;
	}
}

 

int main(int argc, _TCHAR* argv[])

{

	BitMapSortDemo();

	return 0;

}

位图实现

参考:https://blog.csdn.net/ArchyLi/article/details/78573362

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

class BitMap
{
public:
    BitMap(size_t range)
    {
        //此时多开辟一个空间
        _bits.resize(range / 32 + 1);
    }
    void Set(size_t x)
    {
        int index = x / 32;//确定哪个数据(区间)
        int temp = x % 32;//确定哪个Bit位
        _bits[index] |= (1 << temp);//位操作即可
    }
    void Reset(size_t x)
    {
        int index = x / 32;
        int temp = x % 32;
        _bits[index] &= ~(1 << temp);//取反
    }
    bool Test(size_t x)
    {
        int index = x / 32;
        int temp = x % 32;
        if (_bits[index]&(1<<temp))
            return 1;
        else
            return 0;
    }

private:
    vector<int> _bits;
};

void TestBitMap()
{
    BitMap am(-1);
    BitMap bm(200);
    bm.Set(136);
    bm.Set(1);
    cout << bm.Test(136) << endl;
    bm.Reset(136);
    cout << bm.Test(136) << endl;
}

int main()
{
    TestBitMap();
    return 0;
}

bitset和vector< bool >

这里std::bitset使用

  • bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素只占1 bit。
    bitset有一个特性:整数类型和布尔数组都能转化成bitset。
    在定义bitset时,要明确bitset含有多少位,须在尖括号内给出它的长度值:给出的长度值必须是常量表达式

  • 如果想用动态的bit数组,可以试试vector<bool>,vector<bool>是vector的一个模板特化,注意bool类型是8 bits,但是vector<bool>内部也会进行空间优化,vector< bool>里面不是一个Byte一个Byte储存的,而是一个bit一个bit储存的。

但是不提倡使用vector< bool >,

因为它不是容器,不容纳bool类型,因为vector 打包 bool 以节省空间,每个保存在“vector”中的“bool”占用一个单独的bit。
同时禁止有指向单个比特的指针
vector c{ false, true, false, true, false };
bool *p = &c[0]; //错误,不能编译,因为无法将一个临时量地址给绑定到指针

关于bitset和vector<bool>的内存占用大小这里有篇文章
c++中bool数组与bitset,vector的使用与占用空间大小对比

在某些简单的情况下,不想自定义位图的实现时,也可以考虑下用vector<bool>和bitset来实现。
示例:

#include <iostream>       // std::cout
#include<vector>
using namespace std;

int main ()
{
  vector<int> nums{0,-2,1,-3,9,42,10,4,34,33,6,13,5,-12,11,-8,57,15,74};
  //先找出nums中的最大值和最小值
  int minNums=INT_MAX,maxNums=INT_MIN;
  for(auto &i:nums){
    if(i<minNums) minNums=i;
    if(i>maxNums) maxNums=i;
  }
  //将[minNums,maxNums]区间转换到[0,newMaxNums]
  //将nums中每个元素减minNums即可实现

  //注意bool是8 bits
  //但是vector<bool>是vector的一个模板特化,内部会进行空间优化,保证bool类型在里面是1bit存储的。
  vector<bool> temp(maxNums-minNums+1,false);
  for(auto &i:nums){
    temp[i-minNums]=true;//区间start前移到0
  }

  //看看temp的内存占用大小
  //注意sizeof用于vector时,结果跟vector中的元素无关,只是返回这个vector<>类型的大小。
  //cout<<"sizeof(temp)="<<sizeof(temp)<<endl;
  //这里用temp.capacity()来输出vector<bool>类型的容量,单位为bit
  cout<<"temp.capacity()="<<temp.capacity()<<"bits"<<endl;//此处的大小单位为bit

  for(int i=0;i<temp.size();i++)
  {
    if(temp[i]==true)
         cout<<i+minNums<<" ";//区间start恢复
  }

  system("pause");
  return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值