C语言实现位数组(bit数组)与位数组的简单应用举例

  • 学习交流加(可免费帮忙下载CSDN资源):
  • 个人微信: liu1126137994
  • 学习交流资源分享qq群1(已满): 962535112
  • 学习交流资源分享qq群2: 780902027

今天有朋友遇到一个笔试题:一个 4096位的bit数组,要找出前10个二进制的1 所在的位置,麻烦写一个函数来实现

bit数组对我来说是一个新的概念,故整理资料学习bit数组的概念~

加qq1126137994一起学习更多技术!!!

文章目录

  • 1、位数组的概念
    • 将一个整数添加到二进制数组中 :
    • 判断一个整数是否在二进制数组中
    • 删除二进制数组中的一个整数
    • 完整代码

1、位数组的概念

所谓的位数组,主要是为了有效地利用内存空间而设计的一种存储数据的方式。在这种结构中一个整数在内存中用一位(1 bit)表示。这里所谓的表示就是如果整数存在,相应的二进制位就为1,否则为0。

主要思想:我们知道一个 char 类型的数据在内存中占用 1Byte(即 8 bit),如果我们用二进制位在内存中的顺序来代表整数则可以存储更多的信息。

这样的话,一个 char 类型可以存储 8个整数。假设 a是一个 char 数组的话,整数8就可以用 a[1] 的第一个二进制位表示了。那么512字节就是4096位,第一位代表0,第二位代表1,第三位代表2,第4096位代表4095,这样我们就可以用512字节存储4096个数了,大大的节省了内存空间。

这里的关键就是 一个char型能表示8个整数。

下面我实现一种利用 char 数组构造一个二进制数组。主要包括以下三个方面::

将一个整数添加到二进制数组中 :

void add_to_bitarray(char *bitarr, int num){   /* num代表要插进数组中的数 */bitarr[num >> SHIFT] |= (1 << (num & MASK));  /* MASK 为 0x7 */
}

该方法的主要作用是将二进制数组中表示该整数的位置为1。首先我们得找到该整数位于 char 数组的第几个元组中,这里利用该整数除以8即可(代码中除以8用右移三位实现),例如整数25位于25/8 = 3 余 1,表明该整数是用char 数组的第四个元素的第二位表示。那么在该元素的第几位可以利用该整数的后三位表示(0~7刚好可以表示8个位置),即 25 & 0x7 = 1,则代表25在该元素的第二位。将相应位置1,可以先将整数1左移相应位数,然后与二进制数组进行或操作即可。

判断一个整数是否在二进制数组中

int is_in_bitarray(char *bitarr, int num){return bitarr[num >> SHIFT] & (1 << (num & MASK));
}

先找到该整数在二进制数组中的位置,然后判断该位是否为1,若是则表示该整数位于二进制数组中,反之不在数组中。

删除二进制数组中的一个整数

void clear_bitarray(char *bitarr, int num){bitarr[num >> SHIFT] &= ~(1 << (num & MASK));
}

思路相同,先找到该整数在二进制数组中的位置,然后将该位置为0即可。

完整代码

完整的代码如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#define SHIFT 3  
#define MASK 0x7  char *init_bitarray(int);
void add_to_bitarray(char *, int);
int is_in_bitarray(char *, int);
void clear_bitarray(char *, int);
void test(char *);int main(){char *arr;arr = init_bitarray(100);add_to_bitarray(arr, 25);test(arr);clear_bitarray(arr, 25);test(arr);getchar();return 0;
}char *init_bitarray(int size){char *tmp;tmp = (char*)malloc(size / 8 + 1);memset(tmp, 0, (size / 8 + 1)); //initial to 0  return tmp;
}void add_to_bitarray(char *bitarr, int num){   /* num代表要插进数组中的数 */bitarr[num >> SHIFT] |= (1 << (num & MASK));
}int is_in_bitarray(char *bitarr, int num){return bitarr[num >> SHIFT] & (1 << (num & MASK));
}void clear_bitarray(char *bitarr, int num){bitarr[num >> SHIFT] &= ~(1 << (num & MASK));
}void test(char *bitarr){if (is_in_bitarray(bitarr, 25) != 0)printf("25 in\n");elseprintf("25 not in\n");if (is_in_bitarray(bitarr, 30) != 0)printf("30 in\n");elseprintf("30 not in\n");
}

以上是对位数组概念的理解,以及如何创建位数组!
在VS中运行结果如下:
这里写图片描述

  • 下面来解决我们最开始留下的笔试题:

一个 4096位的bit数组,要找出前10个二进制的1 所在的位置,麻烦写一个函数来实现。

假设我们这个数组存储的是char类型的512字节,我们利用上面的函数,来构造bit数组,可以往特定的位填1,然后写出函数来查找前10个1所在的位置,并返回位置:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  #define N_bit  4096
#define SHIFT 3  
#define MASK 0x7  char *init_bitarray(int);
void add_to_bitarray(char *, int);char *init_bitarray(int size){char *tmp;tmp = (char*)malloc(size / 8 + 1);memset(tmp, 0, (size / 8 + 1)); //initial to 0  return tmp;
}void add_to_bitarray(char *bitarr, int num){   /* num代表要插进数组中的数 */bitarr[num >> SHIFT] |= (1 << (8 - (num & MASK)));
}void add_1_to_bitarr(char *bit_arr)
{add_to_bitarray(bit_arr, 25);add_to_bitarray(bit_arr, 28);add_to_bitarray(bit_arr, 23);add_to_bitarray(bit_arr, 67);add_to_bitarray(bit_arr, 35);add_to_bitarray(bit_arr, 36);add_to_bitarray(bit_arr, 55);add_to_bitarray(bit_arr, 69);add_to_bitarray(bit_arr, 44);add_to_bitarray(bit_arr, 97);add_to_bitarray(bit_arr, 421);add_to_bitarray(bit_arr, 564);add_to_bitarray(bit_arr, 987);add_to_bitarray(bit_arr, 684);add_to_bitarray(bit_arr, 986);add_to_bitarray(bit_arr, 658);add_to_bitarray(bit_arr, 354);add_to_bitarray(bit_arr, 764);add_to_bitarray(bit_arr, 691);add_to_bitarray(bit_arr, 36);add_to_bitarray(bit_arr, 345);
}
int main()
{char *bit_arr;bit_arr = init_bitarray(4096);add_1_to_bitarr(bit_arr);int num[10];int k = 1;for (int i = 0; i < N_bit / 8 + 1; i++){for (int j = 1; j < 8 && k <= 10; j++){if ((bit_arr[i] & 128) == 128){num[k] = i * 8 + j + 1;k++;}bit_arr[i] <<= 1;}}for (int n = 1; n <= 10; n++){printf("第%d个1位置为:%d位\n", n, num[n]);}//getchar();return 0;
}

运行结果为:
这里写图片描述

我们看到前10 个1 的位置都比我们填入到数组中的位置大1,是因为我们认为4096位是从第一个1开始,而数组是从第0号开始,所以产生了偏移!!!

到此我们已经用了一种方法来解决这个笔试题,同时也学会了一个新的概念,位数组!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【常见笔试面试算法题12】动态规划算法案例分析

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 文章目录1、暴力搜索方法2、记忆搜索方法3、动态规划方法4、各种动态规划方法案例总结&#xff1a;给定数组arr&#xff0c;arr中所有数都为正数&…

kafka 思维导图

最近在培训沟通力过程中&#xff0c;一句话说的特别好&#xff0c;有输入就要有输出&#xff0c;最近又学习了一遍kafka 给大家分享一下

【C++深度剖析教程28】C++对象模型分析

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 今天记录学习的内容是&#xff1a;C对象模型分析&#xff01;&#xff01;&#xff01; 本质分析&#xff1a; class是一种特殊的struct 在内存中cl…

【C++深度剖析教程29】C++对象模型分析下

加qq1126137994&#xff0c;微信&#xff1a;liu1126137994 一起学习更多技术&#xff01;&#xff01;&#xff01; 今天来继续学习C对象模型&#xff01; 在C编译器内部&#xff0c;类可以理解为结构体子类是由父类成员叠加子类新成员得到的 下面来写一个程序分析C的继承…

java 思维导图

最近有时间&#xff0c;又整理了一下java 思维导图&#xff0c;持续优化中 子模块拆分总结&#xff1a;java基础 java思维导图 总结

【常见笔试面试算法题12续集一】动态规划算法案例1台阶问题练习题

加qq1126137994 一起学习更多技术&#xff01;&#xff01;&#xff01; 以下问题&#xff0c;都可以用非动态规划的方法做&#xff0c;我为了整理动态规划的方法思路&#xff0c;就全部用动态规划的思路来解决问题&#xff0c;这样还可以简化问题的处理&#xff0c;是时间复杂…

linux 思维导图

工作中使用总结的linux 分享一下

【常见笔试面试算法题12续集二】动态规划算法案例2矩阵最小路径和练习题

加qq1126137994 一起学习更多技术&#xff01;&#xff01;&#xff01; 有一个矩阵map&#xff0c;它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走&#xff0c;最后到达右下角的位置&#xff0c;路径上所有的数字累加起来就是路径和&#xff0c;返回所有的…

mysql数据库思维导图

先前总结的一下数据库的思维导图&#xff0c;和大家分享一下&#xff0c;持续更新&#xff1b; 最近面试数据仓库工程师&#xff0c;过程中&#xff0c;问到索引类型&#xff0c;只是记得&#xff0c;普通索引&#xff0c;唯一索引&#xff0c;还有主键&#xff0c;面试中让说…

【常见笔试面试算法题12续集三】动态规划算法案例分析3 LIS练习题(最长上升子序列)

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 这是一个经典的LIS(即最长上升子序列)问题&#xff0c;请设计一个尽量优的解法求出序列的最长上升子序列的长度。 给定一个序列arr及它的长度n(长度小…

【常见笔试面试算法题12续集四】动态规划算法案例分析4 LCS练习题练习题(最长公共子序列的长度)

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 给定两个字符串A和B&#xff0c;返回两个字符串的最长公共子序列的长度。例如&#xff0c;A"1A2C3D4B56”&#xff0c;B"B1D23CA45B6A”&am…

hive 思维导图

1.整理了word文档&#xff0c;但是感觉没有思维导图清晰 &#xff0c;持续更新中 ​ hive 工作中分享。

结构思考力思维导图

个人提升&#xff0c;喜欢钻研的同时&#xff0c;需要增加一下&#xff0c;其他方面的知识&#xff0c;分享一下&#xff1a;

常用内存分配函数的说明

下面哪种C/C 分配内存的方法会将分配的空间初始化为0 A malloc() B calloc() C realloc() D new[ ] 1) malloc 函数&#xff1a; void *malloc(unsigned int size) 在内存的动态分配区域中分配一个长度为size的连续空间&#xff0c;如果分配成功&#xff0c;则返回所分配…

前端学习(120):css精灵和好处

精灵图的目的&#xff1a;很多大型网站在首次加载的时候需要加载很多小图片&#xff0c;如果在同一时间&#xff0c;服务器又拥堵的话&#xff0c;就会导致页面加载慢。为了解决这一问题&#xff0c;就用了精灵图来解决加载时间过长影响用户体验的问题。 精灵图的本质&#xf…

shell 思维导图

分享一下&#xff1b;

Linux 总线、设备、驱动模型的探究

学习交流加 个人qq&#xff1a;1126137994 个人微信&#xff1a;liu1126137994 学习交流资源分享qq群&#xff1a;962535112之前一直做项目&#xff0c;做项目的过程虽然也学习到了不少知识&#xff0c;但是&#xff0c;一直没有好好研究总线设备驱动的机制&#xff0c;今天来学…

二叉树的层序遍历详细讲解(附完整C++程序)

加qq1126137994 微信liu1126137994 一起学习更多技术 1、原理&#xff1a; 层序遍历所要解决的问题很好理解&#xff0c;就是按二叉树从上到下&#xff0c;从左到右依次打印每个节点中存储的数据。如下图&#xff1a; 按层序遍历的原则&#xff0c;打印顺序依次应该是&…

【C++深度剖析教程30】C++中抽象类和接口

加qq1126137994 微信&#xff1a;liu1126137994 1、面向对象中的抽象概念; 在现实中&#xff0c;需要知道具体的图形类型才能知道如何求面积&#xff0c;但是对于抽象的‘图形’&#xff0c;我们是没法求其面积的&#xff0c;而且对其求面积也是没有意义的&#xff1a; cl…