海量数据处理---Bit-Map

原理:Bit-Map就是用一个位来表示某个元素对应的值。采用bit为单位存储数据,大大的节省了空间。如图所示:

例:假设对0-7内的5个元素{3,5,1,6,4}进行排序(不重复)。我们可以使用Bit-Map来做,要表示8个元素,要1个字节空间(8位),故首先开辟1Byte空间,将里面的每一位都置为0。遍历一次元素,将元素的值对应的位变成1。

现在已经将每一个元素对应的位改为1了,所以现在遍历这些位,将值为1的输出即可得到排序的结果。

 

实现难点:

假设有数据32,则应该把32对应的二进制位变成1,这个逻辑位置应该是a[1]的最低位。

值32应该是上图中红色的位置。所以要将一个值与位对应起来,就要处理两个位置:字节位置(数组下标)+位位置

32的字节位置是1,位位置是0。

字节位置:数据/32(数据右移5位)得到数组下标

位位置:数据%32(与0x1f进行与操作)

c语言实现:

#include<iostream>
using namespace std;

#define MAX 1000000
#define INDEX 5
#define BIT 0x1f
#define NUM 32

int a[1+MAX/NUM]={0};

void set(int n)//将n的逻辑位的二进制位置置为1
{
	a[n>>INDEX]=a[n>>INDEX] | (1 << (n & BIT));
	//n>>INDEX,相当于除以32,得到对应下标
	//n&&BIT,相当于模32,得到对应的位
	//a[n>>INDEX] | (1 << (n && BIT))将对应的位变成1
}

void clear(int n)	//将逻辑位n的二进制位置为0
{
	a[n>>INDEX]=a[n>>INDEX] & (~(1 << (n & BIT)));
}

bool Isexist(int n)//测试n对应的逻辑位的二进制位是否为1
{
	return a[n>>INDEX] & (1<<(n&BIT));
}

//用bit-map表示1000000内的数字,假设是排序
int main()
{
	int tmp[]={2,4,33,1,65,35,87,65,43,24,777,555,333,987,6543,34567,32,43323,22344,34432,224};
	int len=sizeof(tmp)/sizeof(tmp[0]);
	for(int i=0;i<len;i++)
	{
		set(tmp[i]);
	}
	for(int i=0;i<=MAX;i++)
	{
		if(Isexist(i))
		{
			cout<<i<<" ";
		}
	}
	return 0;
}

 

运行结果:

 

Bit-Map应用(排序、查询、去重)

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

分析:如果数是有序的,则可以用二分查找来做,时间复杂度为O(logN),空间复杂度是O(1)。无序的话,就用空间换时间的做法。因为unsigned  int 的取值范围就在40多亿,40*10^8/1024/1024/8=476M,故我们可以申请512M的空间,每一位表示一个unsigned int 的数,然后遍历一次将所有树的逻辑位置为1,然后查询一个数,若该数的逻辑位为1,则表示这个数已经存在,否则数不存在。

时间复杂度:O(n),需要遍历一次所有数,将其逻辑位变成1

空间复杂度:根据取值范围确定

 

优点:运算效率高、占用内存小,如N=10000000,只占用N/8=1250000byte=1.25M

缺点:所有的数据不能重复,故不能对重复的数据进行排序和查询。但是这一特性又可以完成查重的功能,遍历数的时候,检查该逻辑位是否为1,如果已经为1,则表示该数重复。

扩展:布隆筛选器https://blog.csdn.net/ShWe_yayaya/article/details/81834986

猜你喜欢

转载自blog.csdn.net/ShWe_yayaya/article/details/81835617