海量數據處理---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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章