位图 就是bitmap的缩写,是用每一位来存放数的状态的结构,适用于大规模的数据。
位图主要用于海量数据处理,索引,数据压缩等方面。
位图的结构类似于哈希表,位图就是用每一位的0或1来表示一个数的状态。
例如,我们现在有一个文件,这个文件中有数字1,3,5.我们就可以把第1位、第3位、第5位的状态设置为1,其余位为0。
bitmap.h:
#pragma once
#include
#include
#include
#include
#include
typedef uint64_t BitmapType;
typedef struct Bitmap{
BitmapType* data;
BitmapType capacity;
}Bitmap;
void BitmapInit(Bitmap* bm,uint64_t capacity);//初始化
void BitmapDestroy(Bitmap* bm);//销毁
void BitmapSet(Bitmap* bm,uint64_t index);//将某一位置为1
void BitmapUnset(Bitmap* bm,uint64_t index);//将某一位置为0
void BitmapFill(Bitmap* bm);//将所有位都置为1
void BitmapClear(Bitmap* bm);//将所有位都置为0
int BitmapTest(Bitmap* bm,BitmapType index);//测试
void GetOffSet(uint64_t index,uint64_t* n,uint64_t* offset);//测试函数的辅助函数
bitmap.c:
#include"bitmap.h"
void BitmapInit(Bitmap* bm,uint64_t capacity){
if(bm == NULL)
return;
bm->capacity = capacity;
BitmapType size = capacity/(sizeof(bm->data[0])*8)+1;
bm->data = (BitmapType*)malloc(sizeof(BitmapType)*size);
memset(bm->data,0,sizeof(BitmapType)*size);
return;
}
void BitmapDestroy(Bitmap* bm){
if(bm == NULL)
return;
bm->capacity = 0;
free(bm->data);
return;
}
void GetOffSet(uint64_t index,uint64_t* n,uint64_t* offset){
if(n == NULL || offset == NULL)
return;
*n = index / (sizeof(BitmapType)*8);
*offset = index % (sizeof(BitmapType)*8);
return;
}
int BitmapTest(Bitmap* bm,BitmapType index){
if(bm == NULL )
return 0;
if(index >= bm->capacity)
return 0;
uint64_t n,offset;
GetOffSet(index,&n,&offset);
uint64_t ret = bm->data[n] & (0x1ul << offset);
return ret > 0 ? 1 : 0;
}
void BitmapSet(Bitmap* bm,uint64_t index){
if(bm == NULL)
return;
if(index >= bm->capacity)
return;
uint64_t n,offset;
GetOffSet(index,&n,&offset);
bm->data[n] |= (0x1ul << offset);
return;
}
void BitmapUnset(Bitmap* bm,uint64_t index){
if(bm == NULL)
return;
if(index >= bm->capacity)
return;
uint64_t n,offset;
GetOffSet(index,&n,&offset);
bm->data[n] &= ~(0x1ul << offset);
return;
}
void BitmapFill(Bitmap* bm){
if(bm == NULL)
return;
BitmapType size = bm->capacity/(sizeof(bm->data[0])*8)+1;
memset(bm->data,0xff,sizeof(BitmapType)*size);
}
void BitmapClear(Bitmap* bm){
if(bm == NULL)
return;
BitmapType size = bm->capacity/(sizeof(bm->data[0])*8)+1;
memset(bm->data,0x0,sizeof(BitmapType)*size);
}
test.c:
#include"bitmap.h"
#define PRINT_HEAD printf("\n============%s============\n",__FUNCTION__);
void TestInit(){
PRINT_HEAD;
Bitmap bm;
BitmapInit(&bm,100);
printf("capacity ecpect 100,actual %lu\n",bm.capacity);
printf("data expect 0,actual %lu\n",bm.data[0]);
}
void TestDestroy(){
PRINT_HEAD;
Bitmap bm;
BitmapInit(&bm,100);
BitmapDestroy(&bm);
printf("capacity ecpect 0,actual %lu\n",bm.capacity);
printf("data expect NULL,actual %p\n",bm.data[0]);
}
void TestSet(){
PRINT_HEAD;
Bitmap bm;
BitmapInit(&bm,100);
BitmapSet(&bm,50);
uint64_t ret = BitmapTest(&bm,50);
printf("ret expect 1,actual %lu\n",ret);
ret = BitmapTest(&bm,10);
printf("ret expect 0,actual %lu\n",ret);
}
void TestUnset(){
PRINT_HEAD;
Bitmap bm;
BitmapInit(&bm,100);
BitmapSet(&bm,50);
uint64_t ret = BitmapTest(&bm,50);
printf("ret expect 1,actual %lu\n",ret);
BitmapUnset(&bm,50);
ret = BitmapTest(&bm,50);
printf("ret expect 0,actual %lu\n",ret);
}
void TestFill(){
PRINT_HEAD;
Bitmap bm;
BitmapInit(&bm,100);
BitmapFill(&bm);
uint64_t ret = BitmapTest(&bm,50);
printf("ret expect 1,actual %lu\n",ret);
ret = BitmapTest(&bm,0);
printf("ret expect 1,actual %lu\n",ret);
ret = BitmapTest(&bm,99);
printf("ret expect 1,actual %lu\n",ret);
}
void TestClear(){
PRINT_HEAD;
Bitmap bm;
BitmapInit(&bm,100);
BitmapFill(&bm);
uint64_t ret = BitmapTest(&bm,50);
printf("ret expect 1,actual %lu\n",ret);
ret = BitmapTest(&bm,0);
printf("ret expect 1,actual %lu\n",ret);
ret = BitmapTest(&bm,99);
printf("ret expect 1,actual %lu\n",ret);
BitmapClear(&bm);
ret = BitmapTest(&bm,50);
printf("ret expect 0,actual %lu\n",ret);
ret = BitmapTest(&bm,0);
printf("ret expect 0,actual %lu\n",ret);
ret = BitmapTest(&bm,99);
printf("ret expect 0,actual %lu\n",ret);
}
int main(){
TestInit();
TestDestroy();
TestSet();
TestUnset();
TestFill();
TestClear();
return 0;
}
结果演示: