一个很实用的小算法,来自Thinking in C++
它主要解决的是一个高效存储真假标志集合的问题,这里记录一下以便需要时直接拿来使用。
如果我们有一批数据,这些数据可以用 [on] 或[off] 来表示。用一个叫位向量的类来存储它们应该是很方便的。有时,位向量并不是作为应用程序的一个工具来使用,而是作为其他类的一部分。
当然对一组标志进行编码,最容易的方法就是每个标志占一个字节, 但这样会非常浪费空间,比如我们有100个标志位,这样就需要800 个字节,但其实真正有效的只需要100个bits (12 bytes + 4 bits)就够了。
bitvector.cpp
main.cpp
它主要解决的是一个高效存储真假标志集合的问题,这里记录一下以便需要时直接拿来使用。
如果我们有一批数据,这些数据可以用 [on] 或[off] 来表示。用一个叫位向量的类来存储它们应该是很方便的。有时,位向量并不是作为应用程序的一个工具来使用,而是作为其他类的一部分。
当然对一组标志进行编码,最容易的方法就是每个标志占一个字节, 但这样会非常浪费空间,比如我们有100个标志位,这样就需要800 个字节,但其实真正有效的只需要100个bits (12 bytes + 4 bits)就够了。
程序实例:
bitvector.h
#include <iostream>
using namespace std;
#ifndef _BITVECTOR_H_
#define _BITVECTOR_H_
#define BIT_MASK 1
class BitVector
{
public:
BitVector();
BitVector(int bits);
int bits();
void bits(int bits);
int flag(int bit);
void flag(int bit, unsigned char nFlag);
void print();
void clear();
private:
int m_nBits;
int m_nSize;
char* m_pBuff;
};
#endif
bitvector.cpp
#include "bitvector.h"
BitVector::BitVector()
{
m_nBits = 0;
m_pBuff = NULL;
m_nSize = 0;
}
BitVector::BitVector(int bits)
{
int nSize = 0;
m_nSize = 0;
m_nBits = bits;
m_pBuff = NULL;
if (bits > 0)
{
if (bits%8 != 0)
nSize = bits/8 + 1;
else
nSize = bits/8;
m_nSize = nSize;
m_pBuff = (char*)malloc(nSize);
if (m_pBuff == NULL)
m_nBits = 0;
}
}
int BitVector::bits()
{
return m_nBits;
}
void BitVector::clear()
{
memset(m_pBuff, 0, m_nSize);
}
void BitVector::bits(int bits)
{
int nSize = 0;
m_nBits = bits;
if (m_pBuff != NULL)
{
free(m_pBuff);
m_pBuff = NULL;
}
if (bits > 0)
{
if (bits%8 != 0)
nSize = bits/8 + 1;
else
nSize = bits/8;
m_pBuff = (char*)malloc(nSize);
m_nSize = nSize;
if (m_pBuff == NULL)
{
m_nBits = 0;
m_nSize = 0;
}
else
memset(m_pBuff, 0, nSize);
}
}
int BitVector::flag(int bit)
{
int nFlag = 0, nIndex = 0, nOffset = 0;
if ((m_pBuff == NULL) || (bit > m_nBits))
{
cout << "Error the bit vector is empty" << endl;
return -1;
}
if (m_nBits <= 0)
{
cout << "Error bit you set is out of range, the Max value is " << m_nBits << endl;
return -1;
}
nIndex = bit / 8;
nOffset = bit % 8;
nFlag = (m_pBuff[nIndex] >> nOffset) & BIT_MASK;
cout << "get bit : " << bit << " value=";
(nFlag == 1)? cout << 1 << " " :cout << 0 << " " << endl << endl;
return nFlag;
}
void BitVector::flag(int bit, unsigned char nFlag)
{
int i = 0;
int nIndex = 0, nOffset = 0;
unsigned char mask = 0;
if ((m_pBuff == NULL) || (bit > m_nBits))
{
cout << "Error the bit vector is empty" << endl;
return;
}
if (m_nBits <= 0)
{
cout << "Error bit you set is out of range, the Max value is " << m_nBits << endl;
return;
}
if ((nFlag != 0) && (nFlag != 1))
{
cout << "Error flag you set should be 0 or 1 " << endl;
}
nIndex = bit/8;
nOffset = bit%8;
if (nFlag == 1)
{
mask = 1 << nOffset;
m_pBuff[nIndex] |= mask;
}
else
{
mask = ~(1 << nOffset);
m_pBuff[nIndex] &= mask;
}
}
void BitVector::print()
{
int i = 0;
int nIndex = 0, nOffset = 0;
unsigned char nFlag = 0;
cout << "Total Flag bits = " << m_nBits << endl;
for (i = 0; i < m_nBits && m_pBuff != NULL; i++)
{
nIndex = i / 8;
nOffset = i % 8;
nFlag = (m_pBuff[nIndex] >> nOffset) & BIT_MASK;
(nFlag == 1)? cout << 1 << " " :cout << 0 << " ";
}
cout << endl;
}
main.cpp
#include "bitvector.h"
int main()
{
BitVector bvct;
int i = 0;
cout << "create with default custruction" << endl;
bvct.print();
cout << "reset bit to 100" << endl;
bvct.bits(100);
bvct.print();
cout << "set flags" << endl;
for (i = 0; i < 100; i++)
{
if ((i % 2) == 0)
bvct.flag(i, 1);
else
bvct.flag(i, 0);
}
bvct.print();
i = bvct.flag(20);
cout << "clear" << endl;
bvct.clear();
bvct.print();
cin >> i;
return 0;
}