位图

利用位图可以判断某个数字是否在一个大范围数据中

具体代码如下:

①bit_map.h

#pragma once 

#include <stddef.h>
#include <stdint.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);

②bit_map.c

#include "bit_map.h"
#include <stdlib.h>
#include <string.h>

//可以拿65来测试,如果要表示的最大数字是65,则需要2个uint64_t
size_t DataSize(size_t capacity)
{
    return capacity / (sizeof(uint64_t)* 8) + 1;        //uint64_t在该操作系统编译器下占8个字节
}

void GetOffset(size_t index, size_t* n, size_t* offset)
{
    *n = index / (sizeof(uint64_t)* 8); 
    *offset = index % (sizeof(uint64_t)* 8);
}

//capacity表示容量,即位图能保存的最大位
void BitMapInit(BitMap* bm, size_t capacity)
{
    if (bm == NULL)
    {
        return;
    }
    bm->capacity = capacity;
    size_t size = DataSize(capacity);
    bm->data = (uint64_t*)malloc(sizeof(uint64_t) * size);
}

// 把第 index 位置为1 
void BitMapSet(BitMap* bm, size_t index)
{
    if (bm == NULL)
    {
        return;
    }
    if (index >= bm->capacity)
    {
        return;
    }
    size_t n, offset;        //64个bit位表示一个数,n为数字的下标;offset表示具体的bit位
    GetOffset(index, &n, &offset);
    bm->data[n] |= (1ul << offset);        //将指定位设置为1

    //unsigned int    1u
    //long   1l
    //unsigned long   1ul
}

// 把第 index 位置为0 
void BitMapUnset(BitMap* bm, size_t index)
{
    if (bm == NULL)
    {
        return;
    }
    if (index >= bm->capacity)
    {
        return;
    }
    size_t n, offset;        //64个bit位表示一个数,n为数字的下标;offset表示具体的bit位
    GetOffset(index, &n, &offset);
    bm->data[n] &= ~(1ul << offset);        //将指定位设置为0
}

// 测试 index 为是 1 , 还是 0. 如果是1, 就返回1. 否则返回0. 
int BitMapTest(BitMap* bm, size_t index)
{
    if (bm == NULL)
    {
        return 0;
    }
    if (index >= bm->capacity)
    {
        return 0;
    }
    size_t n, offset;       
    GetOffset(index, &n, &offset);
    //在进行按位操作时,切记注意防止整型溢出
    uint64_t ret = bm->data[n] & (1ul << offset); 
    return ret != 0 ? 1 : 0;
}

// 把整个位图所有的位都设为0. 
void BitMapClear(BitMap* bm)
{
    if (bm == NULL)
    {
        return;
    }
    memset(bm->data, 0, sizeof(uint64_t)*DataSize(bm->capacity));
}

// 把整个位图所有的位都设为1. 
void BitMapFill(BitMap* bm)
{
    if (bm == NULL)
    {
        return;
    }
    memset(bm->data, 0xff, sizeof(uint64_t)*DataSize(bm->capacity));       
    //一个字节一个字节的设置为1,一个字节对应8个bit位
}

void BitMapDestroy(BitMap* bm)
{
    if (bm == NULL)
    {
        return;
    }
    bm->capacity = 0;
    free(bm->data);
    bm->data = NULL;
    return;
}

③test.c

#include "bit_map.h"

#include <stdio.h>
#include <windows.h>

#define TEST_HEADER printf("\n\n=======================%s=======================\n",__FUNCTION__)

void TestInit()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 65);
    printf("bm->capacity expect 65,actual %lu\n", bm.capacity);
    size_t size = bm.capacity / (sizeof(uint64_t)* 8) + 1;
    printf("size expect 2,actual %lu\n", size);
    size_t i = 0;
    for (; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }
}

void TestSet()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 127);
    BitMapSet(&bm, 63);

    size_t i = 0;
    for (; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }
}

void TestUnset()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 127);
    BitMapSet(&bm, 63);
    BitMapUnset(&bm, 63);
    size_t i = 0;
    for (; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }
}

void TestBitMapTest()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 127);
    BitMapSet(&bm, 63);

    int ret = BitMapTest(&bm, 63);
    printf("ret expect 1,actual %d\n", ret);

    BitMapUnset(&bm, 63);
    ret = BitMapTest(&bm, 63);
    printf("ret expect 0,actual %d", ret);
}

void TestClear()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 127);

    BitMapSet(&bm, 63);
    BitMapSet(&bm, 1);
    BitMapSet(&bm, 2);
    BitMapSet(&bm, 64);
    BitMapSet(&bm, 65);
    BitMapSet(&bm, 31);

    size_t i = 0;
    for (; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }

    printf("\n");
    BitMapClear(&bm);
    for (i = 0; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }
}

void TestFill()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 127);

    BitMapFill(&bm);
    size_t i = 0;
    for (; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }
}

void TestDestroy()
{
    TEST_HEADER;
    BitMap bm;
    BitMapInit(&bm, 127);
    BitMapSet(&bm, 63);

    size_t i = 0;
    for (; i < bm.capacity / (sizeof(uint64_t)* 8) + 1; ++i)
    {
        printf("[%lu]:%lx  ", i, bm.data[i]);
    }

    printf("\n");
    printf("[销毁后]:\n");

    BitMapDestroy(&bm);
    printf("bm->capacity expect 0, actual %lu\n", bm.capacity);
    printf("bm->data expect NULL, actual %p\n", bm.data);
}

int main()
{
    TestInit();
    TestSet();
    TestUnset();
    TestBitMapTest();
    TestClear();
    TestFill();
    TestDestroy();
    system("pause");
    return 0;
}

结果为:

描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值