哈希结构的变形---位图,位图的应用场景,位图的创建,增加元素,删除元素和查找元素,变形位图。

位图

位图一般用来处理大量数据的问题,比如要在100亿个整数中,查找某个数是否存在。第一想到的是遍历的方法,但是遍历首先要往内存中去存储数据,要将100亿个整型直接存储到内存中是做不到的。这时就可以运用到位图。

什么是位图

位图就是创建一个整型A,用这个整型A的bit位去代替一个储存空间,我们都知道比特位只有0和1,如果为了查找数据是否存在,只有两种状态存在和不存在,可以用1和0去表示,比如整型数组:

int array[8] = {0,5,11,21,17,15,26,30};

array存储了8个整型,占用了32个字节。而如果用比特位的0代表没有数据,1代表数据已经存入,可以将所给数据的数值代表比特位的位置,依次将整型A的对应比特位置为1。

位图如何存储数据

以上面的整型数组为例。
在这里插入图片描述

位图的相关代码如下:

#define N 8
typedef int BM_TYPE;

typedef struct BitMap
{
	unsigned int bit[N];
	int size;
}BitMap,*pBitMap;


void InitBitMap(pBitMap BMap);

void InsertBitMap(pBitMap BMap, BM_TYPE d);

void DeleteBitMap(pBitMap BMap, BM_TYPE d);

BM_TYPE FindBitMap(pBitMap BMap, BM_TYPE d);

void InitBitMap(pBitMap BMap)
{
	int count = N;
	assert(BMap);
	BMap->size = 0;
	while(count--)
		BMap->bit[count] = 0;
}

void InsertBitMap(pBitMap BMap, BM_TYPE d)    //增加数据  对应比特位置1
{
	int byteNo;
	int bitNo;
	assert(BMap);
	byteNo = d/32;
	bitNo = d%32;
	BMap->bit[byteNo] |= (1<<bitNo);
}


void DeleteBitMap(pBitMap BMap, BM_TYPE d)    //删除数据  对应比特位置0
{
	int byteNo;
	int bitNo;
	assert(BMap);
	byteNo = d/32;
	bitNo = d%32;
	BMap->bit[byteNo] &= ~(1<<bitNo);
}

BM_TYPE FindBitMap(pBitMap BMap, BM_TYPE d)      //查找数据
{
	int byteNo;
	int bitNo;
	BM_TYPE NewNo;
	assert(BMap);
	byteNo = d/32;
	bitNo = d%32;
	NewNo = BMap->bit[byteNo];
	NewNo |= (1<<bitNo);
	if(NewNo == BMap->bit[byteNo])
		return 1;
	else
		return 0;
}

由于数据量很大,数据值分布不均匀,可以采用哈希存储的结构。先用哈希函数将数据改变为我们所能保存(比如开辟一个整型只能保存32个数,两个整型可以保存64个数,以此类推)的地址值,再去存储。

位图的变形

普通的位图只能表示0和1,存储数据的两种状态存在和不存在,如果数据有可能出现多次,而要找到只出现一次的数据,就需要对位图进行变形。将之前每个数据只用一位比特位,变成两位比特位。00代表不存在、01代表出现一次、10和11都代表出现多次。
在这里插入图片描述
从上图中就可以看出,变形位图明确表示了0、1、6、11都只出现了1次。
变形位图的相关代码:


typedef unsigned int BMD_TYPE;

typedef struct BitMapD
{
	BMD_TYPE* arr;
	int size;
	int capacity;
}BitMapD,*pBitMapD;


void InitBitMapD(pBitMapD bmd);
void InsertBitMapD(pBitMapD bmd,BMD_TYPE d);
void DeleteBitMapD(pBitMapD bmd,BMD_TYPE d);
int  CountBitMapD(pBitMapD bmd,BMD_TYPE d);
void DestroyBitMapD(pBitMapD bmd);

void InitBitMapD(pBitMapD bmd)
{
	assert(bmd);
	bmd->arr = NULL;
	bmd->capacity = 3;
	bmd->arr = (BMD_TYPE*)malloc(sizeof(BMD_TYPE)*bmd->capacity);
	if(NULL == bmd->arr)
	{
		assert(0);
		return;
	}
	memset(bmd->arr,0,bmd->capacity*4);
	bmd->size = 0;
}

void InsertBitMapD(pBitMapD bmd,BMD_TYPE d)    
{
	int byteNo;
	int bitNo;
	int tmp;
	assert(bmd);
	byteNo = (d%(bmd->capacity*16))/16;
	bitNo  = (d%(bmd->capacity*16))%16;   
	tmp = bmd->arr[byteNo];    //两个比特位的判断比较麻烦。
	if( (((1<<bitNo*2) | tmp)!= bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp)!= bmd->arr[byteNo]) )
		bmd->arr[byteNo] = bmd->arr[byteNo] | (1<<bitNo*2);
	else if( (((1<<bitNo*2) | tmp) == bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp)!= bmd->arr[byteNo]) )
	{
		bmd->arr[byteNo] = bmd->arr[byteNo] & ~(1<<bitNo*2);
		bmd->arr[byteNo] = bmd->arr[byteNo] | (1<<(bitNo*2+1));
	}
	else
		bmd->arr[byteNo] = bmd->arr[byteNo] | (1<<bitNo*2);
}

void DeleteBitMapD(pBitMapD bmd,BMD_TYPE d)
{
	int byteNo;
	int bitNo;
	int tmp;
	assert(bmd);
	byteNo = (d%(bmd->capacity*16))/16;
	bitNo  = (d%(bmd->capacity*16))%16;   //两个比特位如何判断
	tmp = bmd->arr[byteNo];
	if( (((1<<bitNo*2) | tmp)!= bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp)== bmd->arr[byteNo]) )
	{
		bmd->arr[byteNo] = bmd->arr[byteNo] & ~(1<<(bitNo*2+1));
		bmd->arr[byteNo] = bmd->arr[byteNo] | (1<<bitNo*2);
	}
	else if( (((1<<bitNo*2) | tmp) == bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp)!= bmd->arr[byteNo]) )
		bmd->arr[byteNo] = bmd->arr[byteNo] & ~(1<<bitNo*2);
	else
		bmd->arr[byteNo] = bmd->arr[byteNo] & ~(1<<bitNo*2);
}

int  CountBitMapD(pBitMapD bmd,BMD_TYPE d)
{
	int byteNo;
	int bitNo;
	int tmp;
	assert(bmd);
	byteNo = (d%(bmd->capacity*16))/16;
	bitNo  = (d%(bmd->capacity*16))%16;   //两个比特位如何判断
	tmp = bmd->arr[byteNo];
	if( (((1<<bitNo*2) | tmp)!= bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp)== bmd->arr[byteNo]) )
		return 2;
	else if( (((1<<bitNo*2) | tmp) == bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp)!= bmd->arr[byteNo]) )
		return 1;
	else if( (((1<<bitNo*2) | tmp)!= bmd->arr[byteNo]) && (((1<<(bitNo*2+1)) | tmp) != bmd->arr[byteNo]) )
		return 0;
	else
		return 3;
}

void DestroyBitMapD(pBitMapD bmd)
{
	assert(bmd);
	free(bmd->arr);
	bmd->arr = NULL;
}

猜你喜欢

转载自blog.csdn.net/qq_39487033/article/details/82772803