BitMap也就是我们所说的位图算法,最常用的就是用来压缩数据。
前奏 :
举个例子:你如果使用int类型的数据来标识数字,则每一个数字需要的4个字节才可以标识,而如果你使用bit的话你只需要一位这样数据的压缩量就是 1/32.
比如你通常表示的数字1在计算机中的存储为(当然也可以有小端存储)00000000 | 00000000 | 00000000 | 000000001 ,
而如果你使用位图的概念 只需要对应的每一位的有无来表示一个数字这样 1的32个bit位就可以表示 数字 0-31;
比如一组数:1 3 5 8 9;
我们从小位开始方便书写:
0 1 0 1 0 1 0 0 1 || 1 0 0 0 0 0 0 0 || 0 0 0 0 0 0 0 0 || 0 0 0 0 0 0 0 0||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 。。。。。。。。。。。。。。
我们可以看到对应的 1 3 5 8 9 相应的位置都置为1表示该数字的存在,很简单吧!
接下来就需要考虑如何才可以把一个数字塞到一个位图中, 如何查询位图是否存在这个数,第三如何删除这个在位图中的数;
我们先有两个基本的操作:
index(num) //获取num在位图的中段落,
对应的如果位图选择的是每32位一段则: index(num) = num/32, 也就是你的位图是用int类型来存储;
如果为8位为一段则: index(num) = num/8;
position(num) //获得在该段中的具体位置,同理:
position(num) = num%8; // num & 0x07;
position(num) = num%32; // num & 0x1F;
各段代码:
``
下面贴具体操作的实际代码:(主要看add , clear ,与contain三个函数)
BitMap.cpp
#include"BitMap.h"
#include<iostream>
#include<memory.h>
/**
// author:L
// date: 2018.4.8
// 尚未解决重复输出的问题,可以在适当的位置插上key但违反了最初数据压缩的意思;
**/
BitMap::BitMap():alloc_size_ (100),max_len_(0){
byte_ = new char[alloc_size_];
for(int i=0; i<alloc_size_; i++){
byte_[i] &= 0;
}
//memset(byte_,NULL,sizeof(char)*alloc_size_);
}
//目前所写的size实际上是根据最大的数申请的;
BitMap::BitMap(int size):alloc_size_(size),max_len_(0){
byte_ = new char[alloc_size_]; //失败的时候回触发std::alloc
//可以捕获异常么;
//memset(byte_,0,sizeof(char)*alloc_size_);
for(int i=0; i<alloc_size_; i++){
byte_[i] &= 0;
}
}
BitMap::~BitMap(){
delete [] byte_;
}
//并未考虑无法插入的问题;
void BitMap::add(int num){
if(index(num)>max_len_){
max_len_ = index(num);
}
byte_[index(num)] |= 1<<position(num); //将对应的位置置为1,去重很方便,但是如果不去冲的话需要考虑加key;
}
//可以确定这个数字是否存在用来进行后续的操作,
bool BitMap::contain(int num){
return ((byte_[index(num)]&(1<<position(num)))!=0);
}
void BitMap::clear(int num){
byte_[index(num)] &=(~(1<<position(num)));
}
//可以通过图绘;
void BitMap::add_array(int* array,int size){
for(int i=0; i<size; i++){
add(array[i]);
}
}
void BitMap::sort_and_show(){//这些是不重复的;
//这里实际上需要知道 array的范围进行取舍,或者知道数量的范围;
// byte转换;
int change = 1;
std::cout<<"the max len is"<<max_len_<<std::endl;
for(int i=0; i<=max_len_; i++){
//优化一下;考虑有可能位全空;
if(0 == (byte_[i] | 0)) continue;
for(int j=0; j<=7; j++){
if(0!=(byte_[i]&(change<<j))){ //这一块出问题了;
//证明这一位存在;
std::cout<<i*8+j<<" ";
}
change = 1;
}
}
}
void BitMap::show_every_bit(char ch){
for(int i=0; i<=7; i++){
std::cout<<((ch>>i)&1)<<" ";
}
}
void BitMap::show_bit(){
for(int i=0; i<alloc_size_; i++){
show_every_bit(byte_[i]);
std::cout<<std::endl;
}
}
/*
void BitMap::sort_and_show(vector<int> array){
for(int i=0 ; i<array.size(); i++){
add(array[i]);
}
int change =1 ;
for(int i=0; i<=max_len; i++){
if(0 == (bytes[i] | 0)) continue;
for(int j=0; j<=7; j++){
if(0!=(byte_[i]&(~(change<<j)))){
//证明这一位存在;
cout<<i*8+j<<" ";
}
change = 1;
}
}
}*/
BitMap.h
#ifndef BITMAP_H_INCLUDED
#define BITMAP_H_INCLUDED
#include<vector>
class BitMap{
public:
BitMap();
BitMap(int size);
~BitMap();
void add(int num);
bool contain (int num);
void clear(int num);
void add_array(int* array,int size);
void sort_and_show();
// void sort_and_show(vector<int> array);
inline index(int index){return (index/8);}
inline position(int pos){return (pos & 0x07);}
void show_bit();
void show_every_bit(char ch);
private:
int alloc_size_; // 标定起始的byte数组的大小;
int max_len_; // 表明当前的实际长度;
char* byte_; //还需要区分32与 8的区别;
BitMap(const BitMap&);
BitMap& operator=(const BitMap&);
//inline index(int index){return (index>>8);}
//inline position(int pos){return (pos & 0x07);}
//void show_every_bit(char ch);
};
#endif // BITMAP_H_INCLUDED
main部分:
#include<iostream>
#include"BitMap.h"
using namespace std;
int main(){
BitMap map_;
int a[10]= {1,5,8,9,12,45,13,48,56,57};
map_.add_array(a,10);
map_.sort_and_show();
cout<<endl;
//map_.show_bit();
return 0;
}
``