C++: 模拟实现类bitset

来源:互联网 发布:软件beta版已过期 编辑:程序博客网 时间:2024/05/19 18:40

C++: 模拟实现类bitset

标签: C++ bitset 位运算

by 小威威


1.bitset简介

bitset能实现对数字的位的操作,同时也能通过类似于数组的下标来访问各个位的数值,以执行相应的操作。模拟bitset就是用一个普通的数组来存储数据以达到模拟的目的。

先声明一下,本篇文章并不是讲述标准库中bitset这个类的用法,而是去讲述如何实现一个模拟bitset的类。

众所周知,int类型在64位系统中占4个字节,也就是32位,倘若我建立一个大小为5的数组,那么我就能存储5*32=160个位。然后我可以通过对数组的每个元素单独处理,通过位运算,来实现对位的操作。

2.类的实现

bitset.h如下:

#ifndef BITSET_H#define BITSET_H#include<iostream>#define N 5const int max_length = 32 * N;class bitset {    private:        int a[N];    public:        bitset(); // 初始化全部置0        void set(int pos);  // 将pos位变为1        void reset(int pos); // 将pos位变为0        int count() const;  // 计算1的个数        bool test(int pos) const; // 检测位的数据是否为1        bool any() const;  // 检测是否存在1        bool none() const; // 检测是否不存在1        bool all() const; // 检测是否全为1        bitset& operator&= (const bitset& b);        bitset& operator|= (const bitset& b);        bitset& operator^= (const bitset& b);        bitset& operator= (const bitset& b);        bitset& operator <<= (int pos);        bitset& operator >>= (int pos);        bitset operator~() const;        bitset operator&(const bitset& b) const;        bitset operator|(const bitset& b) const;        bitset operator^(const bitset& b) const;        bitset operator<<(int pos) const;        bitset operator>>(int pos) const;        bool operator== (const bitset& b) const;        bool operator!= (const bitset& b) const;        bool operator[] (int pos) const; // 下标访问        friend std::ostream& operator << (std::ostream& os, const bitset& s) {            for (int i = N-1; i >= 0; i--) {                for (int j = 31; j >= 0; j--) {                    if (s.a[i] & (1 << j)) os << 1;                    else os << 0;                }            }            return os;        }};#endif

要完成该模拟,需要有一定的位运算知识:

  1. &, |, ^, ~, <<, >>,&=, |=, ^=, <<=, >>=所代表的含义以及执行的原理。(不懂的自行查书\百度\google)

  2. 本题需要的位运算的操作:(在最后的代码会呈现这些方法,所以有些方法没有附上代码只讲解了思路)

(1)将第一位变成1:
这个很简单,用位运算符就可以实现。

int i;i = i | 1;

(2)将第一位变成0:

int i;i = i & ~1;

(3)将某位变成0:
由(2)我们可以知道,要将某位变成0,需要&运算。如果我们能够创造出一个数字,其对应位的数字为0,其它位的数字为1,然后对二者进行&运算,就能将那一位变成0了。

(4)将某位变成1:
由(1)我们可以知道,要将某位变成1,需要|运算。如果我们能够创造出一个数字,使其对应为位1,其它位为0,然后对二者进行 | 运算,就能将那一位变成0了。

(5)统计二进制数中1的个数;
这个有两种方法:I.公式法;II. 逐位扫描法。
我们先来谈谈公式法。

int i, count = 0;while (i) {    i &= i-1;    count++;}

换句话来说就是”1的个数=(i&(i-1))的执行次数”。

第二种法方法就是逐位扫描法。

int num, count = 0;for (int i = 0; i < 32; i++) {    if (num & (1<<i)) count++;}

(6)检验某位是0还是1。
在(5)中的if的条件就是用来判断位是0还是1.因为num & (1<<i)在对应位为1时返回非0值,在对应位为0时返回0.

但是,我个人觉得最有意思的部分就是实现左移和右移。
有两种方法:
(1)一劳永逸法(质变法):
就是直接将所有位进行左移右移n位。采取的思路是对数组逐个元素进行移位操作,然后将移位后出现的补位进行重新赋值(也就是下一个元素的头几位).
(2)量变法:
就是将所有位进行逐次左移右移1位。

下面是这两种左移右移代码的对比:

// 一劳永逸法bitset& bitset :: operator <<= (int pos) {    for (int i = N-1; i >= 1; i--) {        a[i] <<= pos;        for (int j = 0; j < pos; j++) {            if (test(i*32+j-pos)) {                (*this).set(i*32+j);            } else {                (*this).reset(i*32+j);            }        }    }    a[0] <<= pos;    for (int i = 0; i < pos; i++) {        (*this).reset(i);    }}bitset& bitset :: operator >>= (int pos) {    for (int i = 0; i < N-1; i++) {        a[i] >>= pos;        for (int j = 0; j < pos; j++) {            if (test((i+1)*32+j)) {                (*this).set((i+1)*32+j-pos);            } else {                (*this).reset((i+1)*32+j-pos);            }        }    }    a[N-1] >>= pos;    for (int i = 0; i < pos; i++) {        (*this).set(32*N-1-i);    }}// 量变法bitset& bitset::operator <<= (int pos) {    while (pos--) {        for (int i = N-1; i >= 0; i--) {            if (i == 0) {                a[i] <<= 1;                continue;            }            a[i] <<= 1;            if (a[i-1] & (1 << 31))                a[i] |= 1;            else                a[i] &= ~1;        }    }    return *this;}bitset& bitset::operator>>= (int pos) {    while (pos--) {        for (int i = 0; i < N; i++) {            if (i == N-1) {                a[i] >>= 1;                continue;            }            a[i] >>= 1;            if (a[i+1] & 1)                a[i] |= 1 << 31;            else                a[i] &= ~(1 << 31);        }    }    return *this;}

下面呈现实现该类的完整代码:

/*int a[N];*/# include "Bitset.h"#define N 5bitset :: bitset() {    for (int i = 0; i < N; i++) {        a[i] = 0;    }}void bitset :: set(int pos) {    int i = pos / 32;    int j = pos % 32;    a[i] = a[i] | (1 << j);}void bitset :: reset(int pos) {    int i = pos / 32;    int j = pos % 32;    int value = 0;    a[i] &= (~value^(1 << j));}int bitset :: count() const {    int num[N];    for (int i = 0; i < N; i++) {        num[i] = a[i];    }    int count = 0;    for (int i = 0; i < N; i++) {        while (num[i]) {            count++;            num[i] &= num[i]-1;        }    }    return count;}bool bitset :: test(int pos) const {    int i = pos / 32;    int j = pos % 32;    if (a[i] & (1 << j)) {        return true;    }    return false;}bool bitset :: any() const {    for (int i = 0; i < N; i++) {        for (int j = 0; j < 32; j++) {            if (a[i] & (1 << j)) {                return true;            }        }    }    return false;}bool bitset :: none() const {    for (int i = 0; i < N; i++) {        if (a[i] != 0) {            return false;        }    }    return true;}bool bitset :: all() const {    for (int i = 0; i < N; i++) {        if (~a[i] != 0) {            return false;        }    }    return true;}bitset& bitset :: operator&= (const bitset& b) {    for (int i = 0; i < N; i++) {        a[i] &= b.a[i];    }    return *this;}bitset& bitset :: operator|= (const bitset& b) {    for (int i = 0; i < N; i++) {        a[i] |= b.a[i];    }    return *this;}bitset& bitset :: operator^= (const bitset& b) {    for (int i = 0; i < N; i++) {        a[i] ^= b.a[i];    }    return *this;}bitset& bitset :: operator= (const bitset& b) {    for (int i = 0; i < N; i++) {        a[i] = b.a[i];    }    return *this;}bitset& bitset :: operator <<= (int pos) {    for (int i = N-1; i >= 1; i--) {        a[i] <<= pos;        for (int j = 0; j < pos; j++) {            if (test(i*32+j-pos)) {                (*this).set(i*32+j);            } else {                (*this).reset(i*32+j);            }        }    }    a[0] <<= pos;    for (int i = 0; i < pos; i++) {        (*this).reset(i);    }}bitset& bitset :: operator >>= (int pos) {    for (int i = 0; i < N-1; i++) {        a[i] >>= pos;        for (int j = 0; j < pos; j++) {            if (test((i+1)*32+j)) {                (*this).set((i+1)*32+j-pos);            } else {                (*this).reset((i+1)*32+j-pos);            }        }    }    a[N-1] >>= pos;    for (int i = 0; i < pos; i++) {        (*this).set(32*N-1-i);    }}bitset bitset :: operator~() const {    bitset copy;    for (int i = 0; i < N; i++) {        copy.a[i] = ~a[i];    }    return copy;}bitset bitset :: operator&(const bitset& b) const {    bitset copy;    for (int i = 0; i < N; i++) {        copy.a[i] = a[i] & b.a[i];    }    return copy;}bitset bitset :: operator|(const bitset& b) const {    bitset copy;    for (int i = 0; i < N; i++) {        copy.a[i] = a[i] | b.a[i];    }    return copy;}bitset bitset :: operator^(const bitset& b) const {    bitset copy;    for (int i = 0; i < N; i++) {        copy.a[i] = a[i] ^ b.a[i];    }    return copy;}bitset bitset :: operator<<(int pos) const {    bitset copy;    copy = *this;    for (int i = N-1; i >= 1; i--) {        copy.a[i] <<= pos;        for (int j = 0; j < pos; j++) {            if (copy.test(i*32+j-pos)) {                copy.set(i*32+j);            } else {                copy.reset(i*32+j);            }        }    }    copy.a[0] <<= pos;    for (int i = 0; i < pos; i++) {        copy.reset(i);    }    return copy;}bitset bitset :: operator>>(int pos) const {    bitset copy;    copy = *this;    for (int i = 0; i < N-1; i++) {        copy.a[i] >>= pos;        for (int j = 0; j < pos; j++) {            if (copy.test((i+1)*32+j)) {                copy.set((i+1)*32+j-pos);            } else {                copy.reset((i+1)*32+j-pos);            }        }    }    copy.a[N-1] >>= pos;    for (int i = 0; i < pos; i++) {        copy.set(32*N-1-i);    }    return copy;}bool bitset :: operator== (const bitset& b) const {    for (int i = 0; i < N; i++) {        if (a[i] != b.a[i]) {            return false;        }    }    return true;}bool bitset :: operator!= (const bitset& b) const {    int count = 0;    for (int i = 0; i < N; i++) {        if (a[i] == b.a[i]) {            count++;        }    }    if (count == N) {        return false;    }    return true;}bool bitset :: operator[] (int pos) const {    int i = pos / 32;    int j = pos % 32;    if (a[i] & (1 << j)) {        return true;    }    return false;}

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


1 0
原创粉丝点击