热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

位数组(bit数组)

使用到位数组的代码,一般出于两个考虑:1.降低存储空间。2.加快查找效率(能迅速判断某个地元素是否在一个集合中)。知识准备1.计算机中的位操作:与(&)、或(|)、非(~)

使用到位数组的代码,一般出于两个考虑: 1. 降低存储空间。2. 加快查找效率(能迅速判断某个地元素是否在一个集合中)。

知识准备

1. 计算机中的位操作: 与(&)、或(|) 、非(~)

  1 & 1 = 1        1 | 1 = 1        ~1 = 0

  1 & 0 = 0        1 | 0 = 1        ~0 = 1                  

  0 & 1 = 0        0 | 1 = 1

  0 & 0 = 0        0 | 0 = 0

2.  左移(<<)和右移(>>)

  左移一位相当于乘以2。左移操作后,右边空缺位自动补0。右移(本文仅考虑逻辑右移)与左移相反方向操作,相当于除以2,左边空缺自动补0。

3. 置1、置0,判断置位。

  eg: x = 221,其二进制为11011101,若要将它的第5位由0变为1(置1),则只须第5位与1或即可

    11011101
    00100000
   |--------
    11111101
若要将它的第4位由1变为0(置0),则只须第4位与0与即可
    11011101
    11101111
   &--------
    11001101
判断第5位是否置1
    11111101
    00100000
   &--------
    00100000  (相与的结果非0则表明相应位已置1,否则置0)

4.  非(~)运算

  eg: x = 221,其二进制为11011101

    11011101
   ~--------
    00100010

实例演示

假设要求11个数(0~10)存储在位数组里,11个数就需要11个bit位, 而1个byte有8个bit位,故须2个byte才能存储11个数。0存储在第0个byte的第0位,1存储在第0个byte的第1位...存储在第1个byte的第0位,9存储在第1个byte的第1位,10存储在第1个byte的第2位。如下

    |high                      low|
|--- 1 byte ---|--- 0 byte ---|
0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0
10 9 8 7 6 5 4 3 2 1 0

一个数x(非负整数)若要存储在位数组里, 会面临两个问题:

1. x存储在第几个byte里?

  因为一个byte可以存储8个bit,那很显然,x应该存储在第(x/8)个byte里。

2. x存储在第(x/8)个byte的第几位上?

  通过观察,x应该存储在第(x%8)位上。

综上, x应该存储在第(x/8)个byte的第(x%8)位上。

在计算机里,位操作比除法和求模操作更高效点。x/8 相当于 x>>3(右移一位,相当于除以2;右移三位,相当于除以8);x%8相当于x&0x7。

我们要使得x存储在位数组里,就是要使得第(x>>3)个byte的第(x&0x7)位上置1。由知识准备第3点的置1,可以得出,要使第0位置1,则与之相与的数为1(00000001);要使第1位置1,则与之相与的数为2(00000010);要使第2位置1,则与之相与的数为4(00000100) ...

由上可得,把x存储在位数组里,则需要:

  bitArray[x>>3] |= (1<<(x&0x7))

进而可以得出,判断x存储在位数组里,则需要返回

       bitArray[x>>3] & (1<<(x&0x7))

把x从位数组里删除,则需要

  bitArray[x>>3] &= ~(1<<(x&0x7))

C语言实现举例

#include 
#include 

#define SHIFT 3  
#define MASK 0x7 

#define BITARRAY_SIZE(size)             ((size >> SHIFT) + 1)
#define BYTE_INDEX(num)                 (num >> SHIFT)
#define ADD_TO_BITARRAY(array, num)		(array[BYTE_INDEX(num)] |= (1 <<(num & MASK)))
#define IS_IN_BITARRAY(array, num)		(array[BYTE_INDEX(num)] & (1 <<(num & MASK)))
#define CLEAR_BITARRAY(array, num)		(array[BYTE_INDEX(num)] &= ~(1 <<(num & MASK)))

//检测
void test(int value)
{
	if (value)
	{
		printf("In the array.\n");
	}
	else
	{
		printf("Not in the array.\n");
	}
}

int main()
{
	//存储0~10这11个数
	int max_size = 11;
	//存储9
	int number = 9;
	char *bitArray = (char*)malloc(BITARRAY_SIZE(max_size) * sizeof(char));
	
	printf("Init: ");
	test(IS_IN_BITARRAY(bitArray, number));

	//9放到位数组上
	ADD_TO_BITARRAY(bitArray, number);
	printf("ADD_TO_BITARRAY: ");
	test(IS_IN_BITARRAY(bitArray, number));
	
	//9从位数组上清除
	CLEAR_BITARRAY(bitArray, number);
	printf("CLEAR_BITARRAY: ");
	test(IS_IN_BITARRAY(bitArray, number));
	
	if (bitArray)
	{
		free(bitArray);
		bitArray = NULL;
	}
	return 0;
}

 

其它比较高级的语言,封装成特定的类去实现位数组,提供了丰富的操作位的方法,比较方便。如:

C++ bitset
C# BitArray
JAVA BitSet
GO

 

 

 


推荐阅读
  • c语言自定义BOOL函数C语言没有BOOL类型变量boolean类型是C++所独有的由于使用BOOL类型可以使代码更具有可读性,很多编程者都在C中自己定义了类似的应用,一般方法有两 ... [详细]
  • 这篇文章将为大家详细讲解有关如何使用C语言strcmp函数,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一 ... [详细]
  • socket8 [命名管道]
    ::命名管道不但能实现同一台机器上两个进程通信,还能在网络中不同机器上的两个进程之间的通信机制。与邮槽不同,命名管道是采用基于连接并且可靠的传输方式,所以命名管道传输数据只能一对一 ... [详细]
  • 文章目录验证性实验求1~n的连续整数和说明放码结果常见算法时间函数的增长趋势分析说明放码结果设计性实验求素数个数说明放码结果求连续整数阶乘的和说明放码结果验证性实验求1~n的连续 ... [详细]
  • 实验七、绕过ASLR 第二部分
    7.1实验环境VM配置:Ubuntu12.04(x86)7.2实验原理什么是爆破?使用爆破技巧,来绕过共享库地址随机化。7.3实验过程7. ... [详细]
  • 1、概念共享内存:共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同malloc()函数向不同进程返回了指向同一个 ... [详细]
  • [二分图]JZOJ 4612 游戏
    DescriptionInputOutputSampleInput44#****#****#*xxx#SampleOutput5DataConstraint分析非常眼熟࿰ ... [详细]
  • 下载器,就是一种网络工具,从网络中接收自己想要的数据。下载器是一个网络客户端。它的下载流程无非就是客户端连接服务器端,然后发送资源下载请求 ... [详细]
  • 使用临时文件tmpnam该函数的功能是产生一个唯一的文件名系统回味该文件分配一块内存来保存临时变量例如下面的代码#includeintmain(){charnam ... [详细]
  • 两种不同方式获取最大值与最小值代码1:#include&amp;amp;lt;stdio.h&amp;amp;gt;intmain(){floatscore[5], ... [详细]
  • 水题。。main.cppPATA1121CreatedbyPhoenixon2018224.Copyright©2018年Phoenix.Allrightsreserve ... [详细]
  • 这篇文章主要讲解了“GradeBook类怎么定义”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Grad ... [详细]
  • *Copyright(c)2016,烟台大学计算机与控制工程学院Allrightsreserved.文件名称:字符串加密.cpp作者:彭友程完成日期&# ... [详细]
  • 原题我们定义“区间的价值”为一段区间的最大值*最小值。一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。求长度分别为1~n的区间的最大价值。保证数据随机因为保证数据随 ... [详细]
  • wyh2000andastringproblemTimeLimit:20001000MS(JavaOthers)MemoryLimit:13107265 ... [详细]
author-avatar
南昌思锐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有