位图

1、概念

位图法就是bitmap的缩写,所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。

我们知道一个1G=1024M,1M=1024K,1K=1024byte,1byte=8bit,所以1个字节等于8bit,也就是8个二进制位,位图法的概念是用一个位(bit)来标记某个数的存放状态,所以节省了大量的空间。

C++的STL中有bitmap类,它提供了很多方法,详见:http://www.cplusplus.com/reference/stl/bitset/

 

2、数据结构

unsigned int bit[N];
在这个数组里面,可以存储 N * sizeof(int) * 8个数据,但是最大的数只能是N * sizeof(int)  * 8 - 1。假如,我们要存储的数据范围为0-15,则我们只需要使得N=1,这样就可以把数据存进去。如下图:

 

 

如果要记录数据【5,7,10】,如下图,在对应位置上记录即可。

 

 

 

3、基础知识

a. 数据的比特位

所有比特的编号方法是:从低字节的低位比特位开始,第一个bit为0,最后一个bit为 n-1。

比如,给出一个数组:int[] array = new int[4]。那么:

a[0] -- a[4] 的比特位分别为:0--31,32--63,64--95,96--127

下面我们依据一个程序探究数组比特位的编号:

#include <iostream>
using namespace std;

int main()
{
    int array[4] = {0,0,0,0};
    for (int i = 0; i < 4; i++) {
        array[i] = 16;
    }
    for (int i = 0; i < 4; i++) {
        array[i] = array[i] >> 4;
        cout << array[i]<<endl;
    }
    return 0;
}

  结果是输出了4个1,也就是说刚开始比特位编排为:0000 0000 0001 0000,使用位运算,使其右移了4位,变为:0000 0000 0000 0001.

b. 位运算和取模

  位运算跟取模运算之间联系微妙,具体可从下面的例子中看出来:

    100%32;100&31

    上述公式的结果是一样的,让我们探究一下他们的原理:

  100%32 的取余运算,将取到一百减去3个32之后的余数为4。 100&31是进行按位与运算,31=0001 1111;100=0110 0100,当他们进行按位与时,大于等于32的那部分将给消去,留下的便是余数。

  当然上述运算成立的条件便是 32对应位置的数必须是2的N次幂。

 

4、相关操作

  • 读操作
  • 写操作
  • 清除
#define SHIFT 5  
#define MAXLINE 32  
#define MASK 0x1F 

bool getbit(int *bitmap1, int i){  
    return bitmap1[i >> SHIFT] & (1 << (i & MASK));  
} 

void setbit(int *bitmap, int i){  
    bitmap[i >> SHIFT] |= (1 << (i & MASK));  
}

void clearbit(int *bitmap, int i){
    bitmap[i >> SHIFT] & ~(1 << (i & MASK));
}

 

5、应用

a. 枚举

  字符串全组合枚举(对于长度为n的字符串,组合方式有2^n种),如:abcdef,可以构造一个从字符串到二进制的映射关系,通过枚举二进制来进行全排序。

null——> 000000

f——> 000001

e——> 000010

ef——> 000011

……

abcedf——> 111111

b. 搜索

设计搜索剪枝时,需要保存已经搜索过的历史信息,有些情况下,可以使用位图减小历史信息数据所占空间。

c. 压缩

(1)在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数?

(2)腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

 

posted @ 2020-06-04 15:16  r1-12king  阅读(236)  评论(0编辑  收藏  举报