https://blog.csdn.net/freeelinux/article/category/6348840
用位向量实现集合,采用16位无符号短整数数组bit_vector[]作为集合元素的存储,1和0分别表示在或不在集合之中。如何将集合元素i的值存入位向量之中,采用put_member()函数实现,取出采用get_member()实现。下文会给出程序。
用位向量来存储集合元素,这些集合元素只具有整数类型,集合元素的范围在0~set_size-1之间,数组采用16位无符号短整数实现映射。
集合操作主要有交,并,差。
并:利用位运算或 | 实现
交:里用位运算与 &实现
差:举个例子:如 主体数组: 10011001
参数数组: 00111000
差: 10000001
可见是用 主题数组 & ~参数数组即得到结果
程序实现有两需要注意:
1.在初始化时,我们使用的是集合元素数目作为初始化参数,来解析出数组应有的空间大小。解析方式为 (set_size + 15) >> 4,注意:不能是 set_size/16+1 或者 set_size/17+1
它们分别在set_size值为16和33时候失效
2.put member时,我们首先得到该集合元素所在的unsigned short类型,并确定在该类型中是第几位。
auto pos = get_elem_and_pos(x);
unsigned short elem = bit_vector_[pos.first];
unsigned short tmp = elem >> (15 - pos.second);
elem <<= (pos.second + 1); // !!! +1
if(((tmp & 1) == 0) && v)
tmp += 1;
else if(((tmp & 1) == 1) && !v)
tmp -= 1;
bit_vector_[pos.first] = (elem >> (pos.second+1)) | (tmp << (15-pos.second));
我们先用tmp取出该位,然后把原有元素向左移到头!为什么呢?因为这样做了之后,我们由于在后面 | 运算要和改动的数据进行合并,这是我们把原有元素再右移回来,无符号数右移,最高位全为0,这样和改动的元素 | 运算就不会有影响了。
代码如下:
#ifndef _BIT_SET_H
#define _BIT_SET_H
#include <iostream>
#include <vector>
#include <assert.h>
#include <string.h>
const int DEFAULT_SIZE = 100;
template <typename T> //template T for char, short, int, long ...
class bit_set {
public:
bit_set(int sz=DEFAULT_SIZE);
bit_set(const bit_set<T>& other);
~bit_set();
public:
void put_member(const T& x, bool v = true);
bool get_member(const T& x) const;
bool add_member(const T& x);
bool del_member(const T& x);
bit_set<T> operator+(const bit_set<T>& other);
bit_set<T> operator*(const bit_set<T>& other);
bit_set<T> operator-(const bit_set<T>& other);
bool operator==(bit_set<T>& other);
bool contains(const T& x);
bool sub_set(bit_set<T>& other);
int get_set_size() const;
private:
std::pair<int, int> get_elem_and_pos(const T& x) const;
void assert_is_valid(const T& x) const;
private:
unsigned short* bit_vector_;
int vector_size_;
int set_size_;
};
template <typename T>
bit_set<T>::bit_set(int sz)
: set_size_(sz)
{
assert(sz > 0);
vector_size_ = (set_size_ + 15) >> 4;
bit_vector_ = new(std::nothrow) unsigned short[vector_size_];
assert(bit_vector_ != NULL);
std::fill(bit_vector_, bit_vector_+vector_size_, 0);
}
template <typename T>
bit_set<T>::bit_set(const bit_set<T>& other)
{
set_size_ = other.set_size_;
vector_size_ = other.vector_size_;
bit_vector_ = new(std::nothrow) unsigned short[vector_size_];
assert(bit_vector_ != NULL);
std::copy(other.bit_vector_, other.bit_vector_+vector_size_, bit_vector_);
}
template <typename T>
bit_set<T>::~bit_set()
{
delete []bit_vector_;
bit_vector_ = NULL;
set_size_ = 0;
vector_size_ = 0;
}
template <typename T>
inline int bit_set<T>::get_set_size() const
{
return set_size_;
}
template <typename T>
inline std::pair<int, int> bit_set<T>::get_elem_and_pos(const T& x) const
{
assert_is_valid(x);
return std::pair<int, int>(x >> 4, x & 15); //x/16 and x%16
}
template <typename T>
inline void bit_set<T>::assert_is_valid(const T& x) const
{
assert(x >= 0 && x < set_size_);
}
template <typename T>
void bit_set<T>::put_member(const T& x, bool v)
{
auto pos = get_elem_and_pos(x);
unsigned short elem = bit_vector_[pos.first];
unsigned short tmp = elem >> (15 - pos.second);
elem <<= (pos.second + 1); // !!! +1
if(((tmp & 1) == 0) && v)
tmp += 1;
else if(((tmp & 1) == 1) && !v)
tmp -= 1;
std::cout<<tmp<<std::endl;
bit_vector_[pos.first] = (elem >> (pos.second+1)) | (tmp << (15-pos.second));
}
template <typename T>
bool bit_set<T>::get_member(const T& x) const
{
auto pos = get_elem_and_pos(x);
unsigned short elem = bit_vector_[pos.first];
return ((elem >> (15-pos.second)) & 1);
}
template <typename T>
bool add_member(const T& x)
{
assert_is_valid(x);
if(!get_member(x)){
put_member(x, 1);
return true;
}
return false;
}
template <typename T>
bool del_member(const T& x)
{
assert_is_valid(x);
if(get_member(x)){
put_member(x, 0);
return true;
}
return false;
}
template <typename T>
bit_set<T> bit_set<T>::operator+(const bit_set<T>& other)
{
assert(vector_size_ == other.vector_size_);
bit_set tmp(set_size_);
for(int i=0; i<set_size_; ++i)
tmp.bit_vector_[i] = bit_vector_[i] | other.bit_vector_[i];
return tmp;
}
template <typename T>
bit_set<T> bit_set<T>::operator*(const bit_set<T>& other)
{
assert(vector_size_ == other.vector_size_);
bit_set tmp(set_size_);
for(int i=0; i<set_size_; ++i)
tmp.bit_vector_[i] = bit_vector_[i] & other.bit_vector_[i];
return tmp;
}
template <typename T>
bit_set<T> bit_set<T>::operator-(const bit_set<T>& other)
{
assert(vector_size_ == other.vector_size_);
bit_set tmp(set_size_);
for(int i=0; i<set_size_; ++i)
tmp.bit_vector_[i] = bit_vector_[i] & ~other.bit_vector_[i];
return tmp;
}
template <typename T>
bool bit_set<T>::operator==(bit_set<T>& other)
{
assert(vector_size_ == other.vector_size_);
int res = memcmp(bit_vector_, other.bit_vector_, vector_size_);
return !res;
}
template <typename T>
bool bit_set<T>::contains(const T& x)
{
if(x < 0 || x >= set_size_)
return false;
return get_member(x) ? true : false;
}
template <typename T>
bool bit_set<T>::sub_set(bit_set<T>& other) //is this sub_set of other ?
{
assert(set_size_ == other.set_size_);
for(int i=0; i<set_size_; ++i){
if(bit_vector_[i] & ~other.bit_vector_[i])
return false;
}
return true;
}
#endif
下面是测试代码:
#include <iostream>
#include "bit_set.h"
using namespace std;
template <typename T>
void print(const bit_set<T>& bs)
{
const int size = bs.get_set_size();
for(int i=0; i<size; ++i)
cout<<bs.get_member(i)<<' ';
cout<<endl;
}
int main()
{
bit_set<int> bs(10), bs1(10);
print(bs);
//bs.put_member(1);
bs.put_member(3);
bs.put_member(4);
bs.put_member(9);
print(bs);
//bs1.put_member(2);
bs1.put_member(3);
bs1.put_member(4);
bs1.put_member(5);
print(bs1);
bit_set<int> bs3 = bs - bs1;
print(bs3);
bit_set<int> bs4(bs1);
//cout<<bs.sub_set(bs1)<<endl;
cout<<(bs==bs1)<<endl;
cout<<(bs==bs4)<<endl;
cout<<bs1.contains(1)<<endl;
cout<<bs1.contains(3)<<endl;
bit_set<int> bs5 = bs+bs1;
print(bs5);
bit_set<int> bs6 = bs*bs1;
print(bs6);
bit_set<int> bs7 = bs-bs1;
print(bs7);
//bs.put_member(1, 0);
//print(bs);
return 0;
}
---------------------
作者:FreeeLinux
来源:CSDN
原文:https://blog.csdn.net/FreeeLinux/article/details/53148029
版权声明:本文为博主原创文章,转载请附上博文链接!