BitVector

一个很实用的小算法,来自Thinking in C++

它主要解决的是一个高效存储真假标志集合的问题,这里记录一下以便需要时直接拿来使用。

如果我们有一批数据,这些数据可以用 [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;
}








你可能感兴趣的:(BitVector)