【数据结构】位图

1. Makefile

.PHONY: clean

CC = gcc
CFLAGS = -g -Wall -DDEBUG -std=c99

SOURCE = $(wildcard ./*.c)
BIN = $(patsubst %.c, %, $(notdir $(SOURCE)))

$(BIN): $(SOURCE)
	$(CC) $(CFLAGS) $(SOURCE) -o $@

clean:
	rm -rf $(BIN)

2. bitmap.h

/*
* File Name: bitmap.h
*
* Copyright (c) 2022, c code from sustzc.
* All rights reserved.
*/

#ifndef __BITMAP_H__
#define __BITMAP_H__

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    int *data;
    size_t size;
    size_t capacity;
} bitmap_t;

// 初始化位图
bool init_bitmap(bitmap_t *bitmap, size_t bit_counts);
// 打印位图信息
void print_bitmap_info(const bitmap_t *bitmap);
// 获取比特位的个数
size_t get_bitmap_size(const bitmap_t *bitmap);
// 获取存储位图的容量
size_t get_bitmap_capacity(const bitmap_t *bitmap);
// 设置某个比特位 为 1
void bitmap_set(bitmap_t *bitmap, size_t which);
// 设置所有比特位 为 1
void bitmap_set_all(bitmap_t *bitmap);
// 设置某个比特位 为 0
void bitmap_reset(bitmap_t *bitmap, size_t which);
// 设置所有比特位 为 0
void bitmap_reset_all(bitmap_t *bitmap);
// 反转某个比特位
void bitmap_flip(bitmap_t *bitmap, size_t which);
// 反转所有比特位
void bitmap_flip_all(bitmap_t *bitmap);
// 测试某个比特位是否为 1
bool bitmap_test_one(bitmap_t *bitmap, size_t which);
// 获取比特位为 1 的个数
size_t get_bitmap_counts_of_one(const bitmap_t *bitmap);
// 判断是否有比特位被设置
bool bitmap_any(const bitmap_t *bitmap);
// 判断是否所有比特位都没被设置
bool bitmap_none(const bitmap_t *bitmap);
// 判断是否所有比特位都被设置为 1
bool bitmap_all(const bitmap_t *bitmap);
// 销毁位图
void destroy_bitmap(bitmap_t *bitmap);

#ifdef __cplusplus
}
#endif

#endif // __BITMAP_H__

3. bitmap.c


/*
* File Name: bitmap.c
*
* Copyright (c) 2022, c code from sustzc.
* All rights reserved.
*/

#include "bitmap.h"

#define INT_BIT_COUNTS (32)

bool init_bitmap(bitmap_t *bitmap, size_t bit_counts)
{
    if (NULL == bitmap) {
        return false;
    }

    size_t capacity = bit_counts / INT_BIT_COUNTS;
    capacity += (bit_counts % INT_BIT_COUNTS) ? 1 : 0;

    bitmap->data = (int *)calloc(1, sizeof(int) * capacity);
    if (NULL == bitmap->data) {
        perror("calloc bitmap->data fail");
        return false;
    }

    bitmap->capacity = capacity;
    bitmap->size = bit_counts;

    return true;
}

size_t get_bitmap_capacity(const bitmap_t *bitmap)
{
    return NULL == bitmap ? 0 : bitmap->capacity;
}

void print_bitmap_info(const bitmap_t *bitmap)
{
    printf("in %s\n", __func__);

    size_t i = 0, j = 0, bitmap_capacity = get_bitmap_capacity(bitmap);
    for (; i < bitmap_capacity; ++i) {
        for (j = 0; j < INT_BIT_COUNTS; ++j) {
            if (bitmap->data[i] & (1 << j)) {
                printf("bitmap[%zu][%zu] : 1\n", i, j);
            } else {
                printf("bitmap[%zu][%zu] : 0\n", i, j);
            }
        }
    }

    printf("\n");
}

size_t get_bitmap_size(const bitmap_t *bitmap)
{
    return NULL == bitmap ? 0 : bitmap->size;
}

void bitmap_set(bitmap_t *bitmap, size_t which)
{
    size_t bitmap_size = get_bitmap_size(bitmap);
    if (which > bitmap_size) {
        printf("in %s, which %zu > bitmap size %zu\n",
                __func__, which, bitmap_size);
        return;
    }

    // 计算出存储在哪个数组(数组索引)
    size_t index = which / INT_BIT_COUNTS;
    // 计算出存储在哪个比特位
    size_t bit = which % INT_BIT_COUNTS;

    bitmap->data[index] |= (1 << bit);
}

void bitmap_set_all(bitmap_t *bitmap)
{
    size_t i = 0, bitmap_size = get_bitmap_size(bitmap);
    for (; i < bitmap_size; ++i) {
        bitmap_set(bitmap, i);
    }
}

void bitmap_reset(bitmap_t *bitmap, size_t which)
{
    size_t bitmap_size = get_bitmap_size(bitmap);
    if (which > bitmap_size) {
        printf("in %s, which %zu > bitmap size %zu\n",
                __func__, which, bitmap_size);
        return;
    }

    size_t index = which / INT_BIT_COUNTS;
    size_t bit = which % INT_BIT_COUNTS;

    bitmap->data[index] &= (~(1 << bit));
}

void bitmap_reset_all(bitmap_t *bitmap)
{
    size_t i = 0, bitmap_size = get_bitmap_size(bitmap);
    for (; i < bitmap_size; ++i) {
        bitmap_reset(bitmap, i);
    }
}

void bitmap_flip(bitmap_t *bitmap, size_t which)
{
    size_t bitmap_size = get_bitmap_size(bitmap);
    if (which > bitmap_size) {
        printf("in %s, which %zu > bitmap size %zu\n",
                __func__, which, bitmap_size);
        return;
    }

    size_t index = which / INT_BIT_COUNTS;
    size_t bit = which % INT_BIT_COUNTS;

    bitmap->data[index] ^= (1 << bit);
}

void bitmap_flip_all(bitmap_t *bitmap)
{
    size_t i = 0, bitmap_size = get_bitmap_size(bitmap);
    for (; i < bitmap_size; ++i) {
        bitmap_flip(bitmap, i);
    }
}

bool bitmap_test_one(bitmap_t *bitmap, size_t which)
{
    size_t bitmap_size = get_bitmap_size(bitmap);
    if (which > bitmap_size) {
        printf("in %s, which %zu > bitmap size %zu\n",
                __func__, which, bitmap_size);
        return false;
    }

    size_t index = which / INT_BIT_COUNTS;
    size_t bit = which % INT_BIT_COUNTS;

    return bitmap->data[index] & (1 << bit);
}

size_t get_bitmap_counts_of_one(const bitmap_t *bitmap)
{
    size_t i = 0, count = 0, bitmap_capacity = get_bitmap_capacity(bitmap);

    for (; i < bitmap_capacity; ++i) {
        int num = bitmap->data[i];

        while (num) {
            num &= (num - 1);
            ++count;
        }
    }

    return count;
}

bool bitmap_any(const bitmap_t *bitmap)
{
    size_t i = 0, bitmap_capacity = get_bitmap_capacity(bitmap);

    for (; i < bitmap_capacity; ++i) {
        if (0 != bitmap->data[i]) {
            return true;
        }
    }

    return false;
}

bool bitmap_none(const bitmap_t *bitmap)
{
    return !bitmap_any(bitmap);
}

bool bitmap_all(const bitmap_t *bitmap)
{
    size_t i = 0, bitmap_capacity = get_bitmap_capacity(bitmap);
    // 1, 先检查 前 bitmap_capacity - 1 个整数是否是 全 1
    for (; i < bitmap_capacity - 1; ++i) {
        // 取反后不为 全 0, 说明取反前必然不是 全 1
        if (0 != ~(bitmap->data[i])) {
            return false;
        }
    }

    // 2, 再检查最后一个整数
    for (i = 0; i < bitmap_capacity % INT_BIT_COUNTS; ++i) {
        if (0 == (bitmap->data[bitmap_capacity - 1] & (1 << i))) {
            return false;
        }
    }

    return true;
}

void destroy_bitmap(bitmap_t *bitmap)
{
    if (NULL != bitmap) {
        free(bitmap->data);
        bitmap->data = NULL;
        bitmap->size = 0;
        bitmap->capacity = 0;
    }
}

4. test_bitmap.c

/*
* File Name: test_bitmap.c
*
* Copyright (c) 2022, c code from sustzc.
* All rights reserved.
*/

#include "bitmap.h"

void test()
{
    bitmap_t bitmap;

    printf("init bitmap\n");
    if (!init_bitmap(&bitmap, 40)) {
        printf("init_bitmap fail\n");
        return;
    }

    if (bitmap_none(&bitmap)) {
        printf("\nbitmap set none bit\n");
    }

    printf("bit map size: %zu\n", get_bitmap_size(&bitmap));
    printf("bit map capacity: %zu\n", get_bitmap_capacity(&bitmap));
    print_bitmap_info(&bitmap);

    bitmap_set(&bitmap, 10);
    bitmap_set(&bitmap, 20);
    bitmap_set(&bitmap, 30);

    if (bitmap_any(&bitmap)) {
        printf("\nbitmap set any bits\n");
    }

    print_bitmap_info(&bitmap);

    printf("10 bit: %s\n", bitmap_test_one(&bitmap, 10) ? "1" : "0");
    printf("reset 10th bit\n");
    bitmap_reset(&bitmap, 10);
    printf("10 bit: %s\n", bitmap_test_one(&bitmap, 10) ? "1" : "0");
    printf("flip 10th bit\n");
    bitmap_flip(&bitmap, 10);
    printf("10 bit: %s\n", bitmap_test_one(&bitmap, 10) ? "1" : "0");

    printf("The counts of bit(1): %zu\n", get_bitmap_counts_of_one(&bitmap));
    printf("bit map size: %zu\n", get_bitmap_size(&bitmap));
    printf("bit map capacity: %zu\n", get_bitmap_capacity(&bitmap));

    bitmap_set_all(&bitmap);
    if (bitmap_all(&bitmap)) {
        printf("\nbitmap set all bits\n");
    }

    bitmap_reset_all(&bitmap);
    if (bitmap_none(&bitmap)) {
        printf("\nbitmap set none bit\n");
    }

    bitmap_flip_all(&bitmap);
    if (bitmap_all(&bitmap)) {
        printf("\nbitmap set all bits\n");
    }

    printf("\ndestroy_bitmap\n");
    destroy_bitmap(&bitmap);
    printf("bit map size: %zu\n", get_bitmap_size(&bitmap));
    printf("bit map capacity: %zu\n", get_bitmap_capacity(&bitmap));
}

int main(void)
{
    test();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值