数据结构---位图的实现

在哈希表中,是用一个数组对一个集合进行存储,用于查询查找,在存储时需要将元素的值以及相关信息都要存储进去,就是将其整个结构体都存储与数组的一个位置中。但有时候并不需要知道那么多关于该元素的信息,只是想知道在这个集合中是否存在有某一个元素。这时候据需要使用位图了。

位图也时候一种基本的数据结构,位图是与哈希表有一些联系的,功能上是有一定的相同之处。是将哈希表中用于存储的数组变为了一个二进制位,一个二进制位为一个单位,用于存储信息。我们都知道二进制位的值只有两种可能,一个是 1 另一个就是 0 ,所以我们就可以规定 1 是当前位置为有效位,0 就表示当前位置没有意义。当然我们也可以反过来,只要规定者自己使用时清楚就可以了。这样就有了关于位图的一些操作

bitmap.h

#pragma once
#include<stdio.h>
#include<stddef.h>
#include<stdint.h>
#include<string.h>
#include<stdlib.h>
typedef struct BitMap { 
uint64_t* data; 
size_t capacity; // max bit 
} BitMap; 

void BitMapInit(BitMap* bm, size_t capacity); 

// 把第 index 位置为1 
 void BitMapSet(BitMap* bm, size_t index); 

 // 把第 index 位置为0 
 void BitMapUnSet(BitMap* bm, size_t index); 

 // 测试 index 为是 1 , 还是 0. 如果是1, 就返回1. 否则返回0. 
 int BitMapTest(BitMap* bm, size_t index); 

 // 把整个位图所有的位都设为1. 
 void BitMapFill(BitMap* bm); 

 // 把整个位图所有的位都设为0. 
 void BitMapClear(BitMap* bm); 

 void BitMapDestroy(BitMap* bm); 

用一个uint64变量表示无符号64位整型变量,这个便于代码的移植性。位图中每一个元素都是uint64。

bitmap.c

#include"bitmap.h"
//用于得到当前位图的元素个数。
size_t GetSize(size_t capacity)
{
    return capacity / (8 * sizeof(uint64_t)) + 1;
}

//位图的初始化
//用malooc对位图进行开空间。得到一个数组。
void BitMapInit(BitMap* bm, size_t capacity)
{
    if (bm == NULL)
        return;
    bm->data = (uint64_t*)malloc(8 * GetSize(capacity));
    bm->capacity = capacity;
}
//求得需要查找的元素位于数组中的哪个元素,元素中的哪一位
void GetOffset(size_t index, size_t* n, size_t* offset)
{
    //n 为第几个uint,offset为在这个uint中第几位
    *n = index / (sizeof(uint64_t)* 8);
        *offset = index % (sizeof(uint64_t)* 8);
}
//将给定位置的二进制位置1.
void BitMapSet(BitMap* bm, size_t index)
{
    if (bm == NULL)
        return;
    if (index >= bm->capacity)
        return;
    size_t n;
    size_t offset;
    GetOffset(index, &n, &offset);
    uint64_t ret = 1;
        ret <<=offset;
    bm->data[n] |= ret;
}
//将给定位置置0
 void BitMapUnSet(BitMap* bm, size_t index)
{
    if(bm==NULL)
        return;
    if(index>=bm->capacity)
        return;
    uint64_t ret=0xFFFFFFFFFFFFFFFF;
    size_t n=0;
    size_t offset=0;
    GetOffset(index,&n,&offset);
    ret^=(1ul<<offset);
    bm->data[n]&=ret;
    //bm->data[n] &= ~(1ul << offset);以上两句可以替换为这个,
}
//测试当前位置为0还是为1.
int BitMapTest(BitMap* bm, size_t index)
{
   if(bm==NULL)
       return -1;
   if(index>=bm->capacity)
       return -1;
   size_t n=0;
   size_t offset=0;
   GetOffset(index,&n,&offset);
   //int ret = (bm->data[n]&(1ul<<offset));
   //return ret != 0 ? 1 : 0;
   uint64_t tmp;
   tmp = bm->data[n];
   tmp>>=offset;
   tmp &= 1;
   if(tmp==0)
       return 0;
   else
       return 1;
}
//把所有位都设置为1
void BitMapClear(BitMap* bm)
{
    if(bm==NULL)
        return;
    memset(bm->data,0,GetSize(bm->capacity)*sizeof(uint64_t));
}

void BitMapFill(BitMap* bm)
{
    if(bm==NULL)
        return;
    memset(bm->data,0xFF,GetSize(bm->capacity)*sizeof(uint64_t));
}
//销毁整个位图
//因为之前初始化的时候有用malloc申请空间
//所以现在需要用free释放空间
 void BitMapDestroy(BitMap* bm)
{
    if(NULL == bm)
        return;
    free(bm->data);
    bm->capacity=0;
    bm = NULL;
}

test.c

#define __TESTHEAD__ 
 printf("-------------------------------------------
 %s--------------------------------------------\n",__FUNCTION__);
void TestInit()
{
    BitMap bm;
    size_t capacity = 1000;
    BitMapInit(&bm, capacity);
    printf("capacity: expect 1000   expect %lu", bm.capacity);
}

void TestBitMapSet()
{
    __TESTHEAD__;
    BitMap bm;
    BitMapInit(&bm,150);
    BitMapSet(&bm,20);
    size_t i=0;
    for(;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lu",i,bm.data[i]);
    }
    printf("\n");
}
void TestBitMapUnSet()
{
    __TESTHEAD__;
    BitMap bm;
    BitMapInit(&bm,150);
    BitMapUnSet(&bm,20);
    size_t i;
    for(i=0;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lu",i,bm.data[i]);
    }
    printf("\n");
}
void TestBitMapTest()
{
    __TESTHEAD__;
    BitMap bm;
    BitMapInit(&bm,150);
    BitMapSet(&bm,20);
    int ret = BitMapTest(&bm,20);
    int ret1 = BitMapTest(&bm,110);
    printf("expect 1 ,actual %d\n",ret);
    printf("expect 0 ,actual %d\n",ret1);
}
void TestBitMapClear()
{
    __TESTHEAD__;
    BitMap bm;
    BitMapInit(&bm,150);
    BitMapSet(&bm,20);
    BitMapSet(&bm,125);
    size_t i;
    for(i=0;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lu",i,bm.data[i]);
    }
    printf("\n");
    BitMapClear(&bm);
    for(i=0;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lu",i,bm.data[i]);
    }
    printf("\n");
}
void TestBitMapFill()
{
    __TESTHEAD__;
    BitMap bm;
    BitMapInit(&bm,150);
    BitMapSet(&bm,20);
    BitMapSet(&bm,125);
    size_t i;
    for(i=0;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lx",i,bm.data[i]);
    }
    printf("\n");
    BitMapFill(&bm);
    for(i=0;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lx",i,bm.data[i]);
    }
    printf("\n");
}
void TestBitMapDestroy()
{
    __TESTHEAD__;
    BitMap bm;
    BitMapInit(&bm,150);
    BitMapSet(&bm,20);
    BitMapSet(&bm,125);
    size_t i;
    for(i=0;i<GetSize(bm.capacity);i++)
    {
        printf("[%lu]:%lx",i,bm.data[i]);
    }
    printf("\n");
    BitMapDestroy(&bm);
    printf("capacity  expect : 0   actual : %lu\n",bm.capacity);
}
void test()
{
    TestInit();
   TestBitMapSet();
   TestBitMapUnSet();
   TestBitMapTest();
   TestBitMapClear();
   TestBitMapFill();
   TestBitMapDestroy();
}
int main()
{
    test();
    return 0;
}

测试结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值