位图
一、位图的原理:在位图中采用比特位表示对应的元素存在或者不存在0:不存在 1:存在,例如一个int整数有32个比特位可以 表示0-31个整数。
二、位图的优点:使用位图最大的优点就是节省空间。
位图的缺点:①可读性差 ②存储元素的个数比一般元素要多,但是存储元素的大小受空间大小的限制
位图的实现
位图主要的基本操作:
- 设置某一位有效(这里默认有效的含义是将对应比特位置为1)
- 设置某一位无效(这里默认有效的含义是将对应比特位置为0)
请看代码:
//BitMap.h
#pragma once
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
typedef struct BitMap
{
int* _pBit;
int _capacity;
int size; //比特位为1的个数
}BitMap;
void InitBitMap(BitMap* bm, int totalbit); //初始化
void SetBitMap(BitMap* bm, int which); //置1
void UnSetBitMap(BitMap* bm, int which); //置0
//BitMap.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "BitMap.h"
void InitBitMap(BitMap* bm,int totalbit)
{
int capacity = 0;
assert(bm);
capacity = (totalbit / 32) + 1; ////一个int可以表示32个元素,totalbit个元素需要size/32 + 1个int来存储
//注意+1因为1/32 = 0,但是我们需要一个int
bm->_pBit = (int*)malloc(capacity);
if (NULL == bm->_pBit)
{
assert(0);
return;
}
memset(bm->_pBit, 0, sizeof(int)*capacity);
bm->_capacity = capacity;
bm->size = 0;
}
void SetBitMap(BitMap* bm, int which) //bit位 置1
{
int index = 0;
int pos = 0;
assert(bm);
index = (which / 32); //所在的哪个整形空间(32bit位)
pos = (which % 32); //所在该整形空间的哪个比特位
bm->_pBit[index] |= (1 << pos); //置1
printf("%d\n", bm->_pBit[index]);
}
void UnSetBitMap(BitMap* bm, int which) // bit位 置0
{
int index = 0;
int pos = 0;
assert(bm);
index = (which / 32);
pos = (which % 32);
bm->_pBit[index] &= ~(1 << pos);
printf("%d\n", bm->_pBit[index]);
}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "BitMap.h"
void test()
{
BitMap bm;
InitBitMap(&bm, 10);
SetBitMap(&bm, 4);
UnSetBitMap(&bm, 4);
}
int main()
{
test();
system("pause");
return 0;
}
位图的应用
- 1)给定100亿个整数,设计算法找到只出现一次的整数。
100亿个整数采用位图存储的话需要1.5G的内存,并且如果需要记录出现次数的话一个比特位
是无法做到的,我们需要2个比特位那么就需要2.5G的内存,如果我们系统的内存不足够的话,
我们需要将100亿个数据分成1000份文件,将每个文件的数据通过位图存储,我们采用两个比特位
00:没有出现,01,出现一次,10出现多次,11舍弃,再将这1000个文件中出现一次的数据,
统计到一个文件里 - 2)给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集。
将第一个文件的数据分成1000份存储到位图里,再判断第二份文件中的数据是否在位图中。 - 3)1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数。
我们需要将100亿个数据分成1000份文件,将每个文件的数据通过位图存储,我们采用两个比特位
00:没有出现,01,出现一次,10出现2次,11舍弃,再将这1000个文件中出现不超过两次次的数据