【编程珠玑】自己实现位向量类

最近开始看《编程珠玑》了,传说中的“看起来很眼熟啊,而过几分钟后又得出结论——以前从来没读过”,刚看了第一章的内容,作者思考问题的方式和角度确实很好,前言提示说不要看太快,习题要一道一道跟着做,自己做过再去看答案。

这一章的内容是磁盘排序的问题,用了位向量优化了排序(其实跟计数排序的原理差不多,就是利用所有的关键字在一定的范围内,而这里的关键字还是没有重复的,弄一个位向量,遇到一个值就将它相应的位置置为1,自然可以有O(n)的做法。不过如果范围太过分散就没办法了,因为浪费的内存太多了)。
下面是我自己实现的位向量的类,感觉挺使用的,效率也高,不过没有做过多的exception的handle(比如申请不到想要的内存之类的),只做了下标范围的检查。

#include <stdio.h>
#include <assert.h>
#include <string>
using namespace std;


class MyBitSet
{
    typedef char EType;
    static const int SHIFT = 3, MASK = 0x07;
    int size;
    EType* data;

    void calIndex(int index, int& key, int& then) {
        key = index >> SHIFT;
        then = index & MASK;
    }

public:
    MyBitSet(int size): size(size) {
        int len = (size+sizeof(EType)-1)/sizeof(EType);
        data = new EType[len];
        for (int i = 0; i < size; ++i)
            reset(i);
    }

    // set the bit to be 0
    void reset(int index) {
        assert(index >= 0 && index < size);

        int key, then;
        calIndex(index, key, then);
        data[key] &= ~(EType(1) << then);
    }

    // set the bit to be 1
    void set(int index) {
        assert(index >= 0 && index < size);

        int key, then;
        calIndex(index, key, then);
        data[key] |= (EType(1) << then);
    }

    // test the value of the bit
    bool test(int index) {
        assert(index >= 0 && index < size);

        int key, then;
        calIndex(index, key, then);
        return (data[key] & (EType(1) << then)) > 0;
    }

    // a shortcut to test the value of the bit
    bool operator [] (int index) {
        return test(index);
    }

    // transform the data into a string
    string str() {
        string ans(size, '0');
        for (int i = 0; i < size; ++i)
            if (test(i))
                ans[i] = '1';
        return ans;
    }

    // display the data
    void print() {
        printf("%s\n", str().data());
    }
};

int main() {
    int size = 10;
    MyBitSet s(size);

    s.print();
    for (int i = 0; i < size; ++i) {
        s.set(i);
        s.print();
        s.reset(i);
    }

    s.set(4);
    s.set(5);
    s.set(6);
    for (int i = 0; i < size; ++i)
        if (s[i])
            printf("1");
        else
            printf("0");
    printf("\n");

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值