编程珠玑第一章-位图压缩存储

本文详细解析了如何使用位图来存储和操作数据集合,特别是通过位逻辑运算(与、或、移位)实现元素的设置、删除和检查。位图适用于存储不重复且数值范围有限的整数集合,通过位运算高效地进行集合操作。文中给出了C++代码示例,包括set()、clr()和test()三个函数,分别用于插入元素、删除元素和检查元素是否存在。
摘要由CSDN通过智能技术生成

  位图 可以对数据进行压缩存储和快速排序,第一、要求集合中所有元素不重复(如果,要使用位图存储含重复元素的集合,需要设计更加复杂的位图结构表);第二,要求存储数据集合限制在较小的范围,如果有个别数据非常大,导致存储位图的集合也非常大,不一定节省空间;第三,对于 结合中的每条数据项,只包含单一的一个整数。
  本文主要对编程珠玑第一章,使用位逻辑运算(与、或、移位)来实现位向量所给答案进行解释。

#define BITSPERWORD 32 //要存储元素所要占的位数
#define SHIFT 5//除数,十进制数在存储位图所要在的数
#define MASK 0x1F// 十六进制0x1F对应整数为31,对应二进制的5个1
#define N 100000000//待存储集合中最大数
int a[1+N/BITSPERWORD];//位图向量
void set(int i){		a[i>>SHIFT]  |=  (1<<(i &MASK));}//将正整数i存储在位图中
void clr(int i){		a[i>>SHIFT]  &= ~(1<<(i & MASK));}//删除该数
void test(int i){    return  a[i>>SHIFT]  & 1<<(i & MASK));}//判断该数是否存在

1.set(int i)元素存储过程

  void set(int i){ a[i>>SHIFT] |= (1<<(i &MASK));}
i<<(i&&MASK);等价于对i使用%取余数,确定要将当前int中32位中哪一位设置为1,也即i在该int二进制位图中存储的位置。
  例如假设i = 34,使用%运算得到i%34=2, 应该存储在当前int的第二位。使用位运算确定存储位置的过程如下。
在这里插入图片描述

  因为在0000 0000 0000 0000 0000 0000 0000 0010二进制中,只有1个1,所以与原int中所对应的二进制进行|或操作,只会将右边第二位设置为1。
  Note: 在C++中一个int型数据占4个字节32位,最多可以存储2^5=32个数,所以掩码MASK取31,对应二进制为11111。掩码作用是使用一串二进制代码对目标字段进行位与运算,使用掩码中的0,屏蔽目标字段中的1。

2. void clr(int i)元素删除过程

  1<<(i &MASK)也是确定i在当前int位图中存储位置,~表示将该位置设置为0,其余位置设置为1,再与原int中所对应的二进制位进行&与操作,只会将原位图中i存放位置设置为0。

3. void test(int i)判断元素是否存在

  1<<(i &MASK)也是确定i在当前int位图中存储位置,再与原int中所对应的二进制位进行&与操作,只会将原位图中i存放位置设置为1,怎返回大于零的数,表示存在,原位图中对应位置为0,与完结果为零,表示该元素不存在。

Reference

[1]https://blog.csdn.net/eternal_tree/article/details/78699530.
[2]http://www.voidcn.com/article/p-fawcjwap-ep.html
[3]https://blog.csdn.net/qq_44443986/article/details/117359908

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值