哈希变形---位图

哈希变形---位图(bitmap)

位图是哈希的一种扩展,本质上是一种数组,即每个二进制位表示一种状态,0表示不存在,1表示存在

1>所谓的位图就是用bit位来存放数据的某种状态,适用于大规模的数据.

2>位图结构

我们先来用腾讯的一道大数据题引出位图结构吧。比如说:给40亿个不重复且无序的无符号整数,现在给你一个整数让你快速判断出它是否存在?(假设我们只有4G内存)

40亿个数需要160亿字节,等同于16GB,一次性是无法将40亿个数据加载到内存中的,因此引入了位图。

40亿个数我们只需要知道它存在与不存在,所以我们用40亿个bit位来标识它的存在状态就好.

那么40亿/8=5亿个字节也就是500 000 000 = 0.5G,这样一来就可以解决加载内存的问题了.

那么我们的问题是:一个数据该在哪个字节,以及该字节的哪一位呢.

一个数据arr[i]------我们假如以一个整形空间为一个单元,我们把arr[i]的值记为pos,那么该数据在该整形单元的pos>>5(pos/32)的这个字节中,在该字节的pos%32的bit位上.

3>位图实现

BitMap.h

typedef struct BitMap
{
	int * Bit_bset;//位的集合
	int _capacity;
	int _size;//有效bit位的个数
}BitMap;
void BitMapInit(BitMap * bmp,int capacity);
void BitMapSet_zero(BitMap * bmp,int pos);
void BitMapSet_one(BitMap *bmp,int pos);
int  BitMapTest(BitMap *bmp, int pos);//测试bit位为1还是为0;
int BitMapSize(BitMap *bmp);
int BitMapCount(BitMap *bmp);
void BitMapDestroy(BitMap *bmp);

BitMap.c

#include "BitMap.h"
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
void BitMapInit(BitMap * bmp, int total_Bit){
	assert(bmp); //total_Bit代表总共的bit位数
	bmp->_capacity = (total_Bit >> 5 )+ 1;//代表需要的整形空间的个数
	bmp->Bit_bset = calloc(bmp->_capacity, sizeof(int));//void *calloc(空间的个数,每个空间的字节数);
	bmp->_size = total_Bit;//有效比特位的个数
}
//将pos的位置0;
void BitMapSet_zero(BitMap * bmp, int pos){
	assert(bmp);
	int pos_Byte = pos >> 5;
	int pos_Bit = pos % 32;
	if (pos > bmp->_size)
		return;
	bmp->Bit_bset[pos_Byte] = bmp->Bit_bset[pos_Byte] &( ~(1 << pos));
	
}
//将pos的位置1;
void BitMapSet_one(BitMap *bmp, int pos){
	assert(bmp);
	int pos_Byte = pos >> 5;
	int pos_Bit = pos % 32;
	if (pos > bmp->_size)
		return;
	bmp->Bit_bset[pos_Byte] = bmp->Bit_bset[pos_Byte] |(1 << pos);
	
}
int  BitMapTest(BitMap *bmp, int pos)//测试bit位为1还是为0;
{
	assert(bmp);
	int pos_Byte = pos >> 5;
	int pos_Bit = pos % 32;
	if (pos > bmp->_size)
		return;
	return bmp->Bit_bset[pos_Byte] & (1 << pos);
}
int BitMapSize(BitMap *bmp)
{
	assert(bmp);
	return bmp->_size;
}
//统计bit位上1的个数
int BitMapCount(BitMap *bmp){
	int i = 0;
	int count = 0;
	assert(bmp);
	const char * bit1Count = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";
	for ( i = 0; i <bmp->_capacity; i++)
	{
		int value = bmp->Bit_bset[i];
		int j = 0;
		//一个整数占4个字节,我们按一个字节为单元查看bit位上1的个数
		while (j<sizeof(bmp->Bit_bset[0])){
			char c = value;
			//统计一个字节的底4位
      		        count+=bit1Count[c&0x0f];
			c >>= 4;
			//统计一个字节的高4位
			count+=bit1Count[c&0x0f];
			value >>= 8;
			j++;
		}
	}
	return count;
}
void BitMapDestroy(BitMap *bmp){
	assert(bmp);
	if (bmp->Bit_bset)
		free(bmp->Bit_bset);
	bmp->_size = 0;
	bmp->_capacity = 0;
}

test.c

#include "BitMap.h"
#include<stdio.h>
#include<stdlib.h>
int main(){
	BitMap bmp;
	int i = 0;
	int len = 0;
	int array[] = {1,3,7,4,12,16,19,13,22,18};
	BitMapInit(&bmp, 24);
	len = sizeof(array) / sizeof(array[0]);
	for ( i = 0; i < len; i++)
	{
		BitMapSet_one(&bmp, array[i]);
	}
	if (BitMapTest(&bmp, 22)){
		printf("存在\n");
	}
	if (BitMapTest(&bmp, 20)){
		printf("不存在\n");
	}
	printf("%d\n", BitMapSize(&bmp));
	printf("%d\n", BitMapCount(&bmp));
	system("pause");
	return 0;
}


猜你喜欢

转载自blog.csdn.net/sx2448826571/article/details/80416179