C++:位图总结

1、位图的概念

位图(bitset)是一种常用的数据结构,常用在给一个很大范围的数,判断其中的一个数是不是在其中。在索引、数据压缩方面有很大的应用。

位图是用数组实现的,数组的每一个元素的每一个二进制位都表示一个数据,0表示该数据不存在,1表示该数据存在

如下图:
在这里插入图片描述
一般来说一个位图所占的空间为512M,所以说要判断一个数是否在0~4294967295中需要的空间是512M(即一个位图)来解决。

2、位图的实现

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

class bitset
{
	vector<int> m_bit;
	size_t m_bitcount;//bitset的总大小,相当于capacity
public:
	bitset(size_t bite) :
		m_bit(bite / 32 + 1),
		m_bitcount(bite)
	{

	}

	//给某一位置一
	void set(size_t pos)
	{
		if (pos > m_bitcount)
		{
			return;
		}
		//例:表示1,22,34
		//[0]:00000000 01000000 00000000 00000010
		//[1]:00000000 00000000 00000000 00000100
		//[2]:00000000 00000000 00000000 00000000
		//[3]:00000000 00000000 00000000 00000000
		size_t index = pos / 32;//表示下标
		size_t bits = pos % 32;//表示每组中的位置

		m_bit[index] |= 1u << bits;//置一
	}

	//给某一位置零
	void reset(size_t pos)
	{
		if (pos > m_bitcount)
		{
			return;
		}

		size_t index = pos / 32;//表示下标
		size_t bits = pos % 32;//表示每组中的位置

		m_bit[index] &= ~(1u << bits);//置零
	}

	//判断某一位的结果是0或1
	bool get(size_t pos)
	{
		if (pos > m_bitcount)
		{
			return;
		}

		size_t index = pos / 32;//表示下标
		size_t bits = pos % 32;//表示每组中的位置

		return m_bit[index]  >> bits & 1;
	}

	//位图不支持扩容
	size_t size()
	{
		return m_bitcount;
	}

	//数位图中一共有多少个1
	size_t count()
	{
		const char *pCount = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";
											// 0  1  2 3 4 5  6  7 8 9 a  b  c d e f

		size_t size = m_bit.size();
		size_t count = 0;
		size_t i;
		for (i = 0; i < size; i++)
		{
			int value = m_bit[i];
			for (int j = 0; j < sizeof(m_bit[0]); j++, value >>= 8)
			{
				char c = value;//char类型对value进行截断,相当于取8位
				count += pCount[c & 0x0f];//计算低4位中1的个数
				c >> 4;//右移4后,计算剩下4位中1的个数
				count += pCount[c & 0x0f];
			}
		}
	}
};

3、位图的应用

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

4、例题

  1. 给定100亿个整数,设计算法找到只出现一次的整数?
    思路:利用两个位图,当某个数出现第一次将位图1 对应的位置置1,若出现第二次或者更多次将位图2置1,最终结果若位图1的某个位置为1 ,位图2对应的位置为0时,说明该数字只出现了一次。

  2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
    思路:每个文件各用一个位图,若数字出现将对应的位置置1,最后扫描两个位图,相同位置均为1时,说明该数字为两个文件的交集。

  3. 1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数?
    思路:利用两个位图,位图的状态进行判断:
    若位图1、位图2均为0(表示该数字之前未出现),则将位图1对应的位置置1(变换后为1 0);
    若位图1为1,位图2为0(表示该数字之前出现过1次),则将位图2对应的位置置1(变换后为1 1);
    若位图1、位图2均为1(表示该数字在之前出现过2次),则将位图1对应的位置置0(变换后为0 1);
    若位图1为0,位图2为1(表示该数字在之前出现过三次及以上),不做任何改变;
    所以除了位图1为0,位图2为1对应的数字,其他数字出现的次数不超过2次。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值