数据结构之位图

来源:互联网 发布:urlencoder函数php 编辑:程序博客网 时间:2024/05/27 00:32

前言

因为之前上数据挖掘的课的老师经常在课上提到这种方法,正好我又不会,于是抽点时间出来写一篇Blog学习一下这种数据结构。

问题导入

给定40亿个不重复的unsigned int的整数,没有排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中。

快速思考

C语言总一个int变量占32位,即4个字节,那么如果用一个40亿的数组来存储的话,需要的空间就是40亿x4Bytes = 160亿 Bytes = 14G,显然计算机的内存这样就爆了。所以就引出了位图的方法。

定义

实际上一个int有32位,而我仅仅拿来存储了32个数,如果我每一位都拿来存储一个数呢?比如一个int型变量,我要存储数15,那么就将第15位上置为1,我要存储20,就把第20位上置为1,以此类推,这样我一个int型变量就能存储32个数。
所申请的int数组如下:
这里写图片描述
如何确定某一个数A在哪个位置呢?
首先要得到其在那个字节,即A / 32.
其次要得到在哪一位,即 A % 32
采用位运算可以更快的进行计算。
A/32 = A >> 5(向右移动5次)
A%32 = A & (0x1F)

解决

因此上述的问题就可以只用40亿个bit = 1.25亿个Bytes来解决,显然对内存的要求要低许多。思路就是读取40亿个整数,对于每一个数将某一bit置1,然后对于陌生的数,直接判断其对应的位是1还是0即可。

代码

#define MAX 4000000000#define MASK 0x1F#define DIGITS 32int a[MAX/DIGITS];void set(int num) {//将某数的逻辑位置置1    a[num>>5] |= (1 << (n&MASK)); //num>>5相当于求字节位置,num&MASK相当于求位位置} void clear(int num) {//将某数的逻辑位置清0    a[num>>5] &= (~(1<<(n&MASK)));}void test(int num) {    return a[num>>5] & (1<<(n&MASK));}

C++ STL bitmap头文件中提供了bitmap的实现
http://www.cplusplus.com/reference/bitset/bitset/

#include <iostream>#include<bitset> using namespace std;int main(int argc, char *argv[]){    const int max = 10000000;    int n,i;    bitset<max+1> bit;                     //初始默认所有二进制位为0     while(scanf("%d",&n)!=EOF)    {        bit.set(n,1);                   //将第n位置1                   }        for(i=0;i<=max+1;i++)    {        if(bit[i]==1)            printf("%d ",i);    }    return 0;}

其余应用

1.排序
先将数组中所有的数读进去,然后从低位到高位遍历一遍,即可得到升序的结果。
2.两个数组求交集
用两个位图,然后对两个位图进行与操作,即可得到这两个数组的交集。
等等!

原创粉丝点击