【数据结构(邓俊辉)学习笔记】向量06——位图

文章目录

  • 0.概述
  • 1.结构
  • 2.实现
  • 3. 应用
    • 3.1 去重
    • 3.2 筛法

0.概述

位图(Bitmap)是一种特殊的序列结构,可用以动态地表示由一组(无符号)整数构成的集合。
在这里插入图片描述

  1. test() 判断k 是否存在集合S中。
  2. set() 将k 加入到集合S中。
  3. clear() 将k从集合S中移除。

若是32位,则长度U为 2 32 2^{32} 232,且其中每个元素的取值均为布尔型(初始值均为 false)。

1.结构

在这里插入图片描述
注意:bit的最小操作单位是8位,n+ 7是在做ceiling。

算法思想:

  • test算法:
    第一步:找bit所在基本单位区间,即以8个bit为单位的,k >> 3 即(k/8),即为入口。
    第二步:根据第一步找到的入口,计算offset值,k & 0x07 即(k%8),再生成掩码去操作single bit。
  • set算法 / clear算法:
    与test算法基本相同,将 & 改成 |= 或 &=~。
    在这里插入图片描述
    综上:
  • 就可在O(1)时间完成test set clear操作。
  • 位图向量所占的空间线性正比于集合的取值范。

2.实现

上述接口实现

class Bitmap { //位图Bitmap类
private:unsigned char* M;Rank N, _sz; //位图空间M[],N*sizeof(char)*8个比特中含_sz个有效位
protected:void init( Rank n ){ M = new unsigned char[N = ( n + 7 ) / 8]; memset( M, 0, N ); _sz = 0; }
public:Bitmap( Rank n = 8 ) { init( n ); } //按指定容量创建位图(为测试暂时选用较小的默认值)Bitmap( char* file, Rank n = 8 ) { //按指定或默认规模,从指定文件中读取位图init( n );FILE* fp = fopen( file, "r" ); fread( M, sizeof( char ), N, fp ); fclose( fp );for ( Rank k = 0, _sz = 0; k < n; k++ ) _sz += test(k);}~Bitmap() { delete[] M; M = NULL; _sz = 0; } //析构时释放位图空间Rank size() { return _sz; }void set   ( Rank k ) { expand( k ); _sz++; M[k >> 3] |=   ( 0x80 >> ( k & 0x07 ) ); }void clear ( Rank k ) { expand( k ); _sz--; M[k >> 3] &= ~ ( 0x80 >> ( k & 0x07 ) ); }bool test  ( Rank k ) { expand( k ); return M[k >> 3] &    ( 0x80 >> ( k & 0x07 ) ); }void dump( char* file ) //将位图整体导出至指定的文件,以便对此后的新位图批量初始化{ FILE* fp = fopen( file, "w" ); fwrite( M, sizeof ( char ), N, fp ); fclose( fp ); }char* bits2string( Rank n ) { //将前n位转换为字符串——expand( n - 1 ); //此时可能被访问的最高位为bitmap[n - 1]char* s = new char[n + 1]; s[n] = '\0'; //字符串所占空间,由上层调用者负责释放for ( Rank i = 0; i < n; i++ ) s[i] = test( i ) ? '1' : '0';return s; //返回字符串位置}void expand( Rank k ) { //若被访问的Bitmap[k]已出界,则需扩容if ( k < 8 * N ) return; //仍在界内,无需扩容Rank oldN = N; unsigned char* oldM = M;init( 2 * k ); //与向量类似,加倍策略memcpy_s( M, N, oldM, oldN );delete[] oldM; //原数据转移至新空间}
};
  • 提供了一个dump()接口,可以将位图整体导出至指定的文件,以便对此后的新位图批量初始化。
  • 与可扩充向量一样,一旦即将发生溢出,这里将调用expand()接口扩容。可见,这里采用的也是“加倍”的扩容策略。

3. 应用

3.1 去重

在这里插入图片描述

  • 利用 Bitmap 类设计算法,在 O(n)时间内剔除 n 个 ASCII 字符中的重复字符,各字符仅保留一份
1. 将非重复的ASCII字符视作一个集合,并将其组织为一个Bitmap结构——ASCII编码为k的字符,对应于其中第k个比特位。2. 初始时,该集合为空,Bitmap结构中的所有比特位均处于0状态。以下,只需在O(n)时间内遍历所有的输入字符,并对
ASCII编码为k的字符,通过set(k)接口将其加入集合。3. 请注意,这里使用的Bitmap结构只需128个比特位。因此,最后只需再花费O(128) = O(1)时间遍历一趟所有的比特位,并输出所有通过test()测试的比特位,即可完成字符集的去重。

3.2 筛法

  • 求素数
    算法思想:0和1自然不是,若2是,则认为2的倍数4,6,8均是,依次类推。最后留下来的则是素数。
    在这里插入图片描述
    实现思想:Bitmap B(n),记录待处理的数,0和1自然不是set掉,查看数i是否被set,若没有则以i为步长,set掉取余数。
    在这里插入图片描述
  • 利用 Bitmap 类设计算法,快速地计算不大二 10^8 的所有素数。
#include "../Bitmap/Bitmap.h" //引入Bitmap结极
/******************************************************************************************
* 筛法求素数
* 计算出不大于n的所有素数
* 不计内循环,外循环自身每次仅一次加法、两次判断,累计O(n)
* 内循环每趟迭代O(n/i)步,由素数定理至多n/ln(n)趟,累计耗时不过
* n/2 + n/3 + n/5 + n/7 + n/11 + ...
* < n/2 + n/3 + n/4 + n/6 + n/7 + ... + n/(n/ln(n))
* = O(n(ln(n/ln(n)) - 1))
* = O(nln(n) - nln(ln(n)) - 1)
* = O(nlog(n))
* 如下实现做了进一步优化,内循环从i * i而非i + i开始,迭代步数由O(n / i)降至O(max(1, n / i - i))
******************************************************************************************/
void Eratosthenes ( int n, char* file ) {Bitmap B ( n ); B.set ( 0 ); B.set ( 1 ); //0和1都不是素数for ( int i = 2; i < n; i++ ) //反复地,从下一if ( !B.test ( i ) ) //可认定的素数i起for ( int j = 2*i; j < n; j += i ) //以i为间隔B.set ( j ); //将下一个数标记为合数B.dump ( file ); //将所有整数的筛选标记统一存入指定文件,以便日后直接寻入
}

该算法可在O(nlogn)时间内计算出不超过n的所有素数。

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

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

相关文章

每日OJ题_贪心算法二④_力扣2418. 按身高排序

目录 力扣2418. 按身高排序 解析代码 力扣2418. 按身高排序 2418. 按身高排序 难度 简单 给你一个字符串数组 names &#xff0c;和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i&#xff0c;names[i] 和 heights[i] 表示第 i 个…

【Unity】在空物体上实现 IPointerClickHandler 不起作用

感谢Unity接口IPointerClickHandler使用说明_哔哩哔哩_bilibiliUnity接口IPointerClickHandler使用说明, 视频播放量 197、弹幕量 0、点赞数 3、投硬币枚数 2、收藏人数 2、转发人数 0, 视频作者 游戏创作大陆, 作者简介 &#xff0c;相关视频&#xff1a;在Unity多场景同时编辑…

京东初级运营必修课程,从零开始学习(49节课)

课程内容&#xff1a; 01.1.全面解析店铺后台的各项功能 02.2.商品要素的重要性及如何打造黄金标题 03.3.手把手带你完成商品上架 04.4.为啥你的流量不转化-诸葛 05.5.怎么策划一张高点击率的照片 06.6.内功优化之数据化标题创建 07.7.内功优化之如何高转化活动落地页 …

node应用部署运行案例

生产环境: 系统&#xff1a;linux centos 7.9 node版本&#xff1a;v16.14.0 npm版本:8.3.1 node应用程序结构 [rootRainYun-Q7c3pCXM wiki]# dir assets config.yml data LICENSE node_modules nohup.out output.log package.json server wiki.log [rootRainYun-Q7c…

SpringBoot集成Log2j4指定外部配置文件源码解读

一、背景 程序读取外部log4j2.xml配置文件方式为启动命令添加了--logging.config/path/log4j2.xml&#xff0c;因系统安全整改&#xff0c;将/var/log/目录改为了700&#xff0c;程序使用非root启动时log4j2报错无法在/var/log目录下创建日志文件。经排查发现jar包的classpath…

python的self类

在Python的类&#xff08;class&#xff09;定义中&#xff0c;self 是一个变量名&#xff0c;它代表实例本身。在类定义的方法中&#xff0c;self 总是作为第一个参数&#xff0c;并且这是一个约定俗成的用法。通过 self&#xff0c;你可以访问和操作类的属性&#xff08;vari…

Nacos如何支持服务发现和注册?

Nacos如何支持服务发现和注册 在微服务架构的浪潮中&#xff0c;服务发现和注册成为了支撑整个架构稳定运行的关键技术之一。而Nacos&#xff0c;作为阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台&#xff0c;凭借其简单易用、功能强大的特性&#xff0c;受到了广…

我的创作纪念日—128天的坚持|分享|成长

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&am…

C++进阶-----继承

1、继承的概念和定义 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象 程序设计的层次结构&#xf…

Docker-Compose概述与简单编排部署

目录 前言 一、Docker-Compose 概述 1、Docker-Compose 概念 2、Docker-Compose 优缺点 2.1 Docker-Compose 优点 2.2 Docker-Compose 缺点 3、Docker-Compose与Docker-Swarm的区别 二、两大文件格式 1、YAML 文件格式 2、JOSON 文件格式 3、YAML 与 JOSON 格式的区…

用Rust编写Python扩展

一、用Rust编写Python扩展 用Rust编写Python扩展是完全可行的&#xff0c;并且近年来变得越来越流行。Rust是一种内存安全的语言&#xff0c;它提供了与C语言类似的底层访问能力&#xff0c;但具有更强大的内存安全和并发特性。 为了使用Rust编写Python扩展&#xff0c;你可以…

全志ARM-蜂鸣器

sh操作准备&#xff1a; 1.使Tab键的缩进和批量对齐为4格 在/etc/vim/vimrc 中添加一项配置 set tabstop 4; 也可以再加一行 set nu显示代码的行数 vim的设置&#xff0c;修改/etc/vim/vimrc文件&#xff0c;需要用超级用户权限 /etc/vim/vimrc set shiftwidth4 设置批量…

【刷题篇】动态规划-二维费用的背包问题(十二)

文章目录 1、一和零2、盈利计划3、组合总和 Ⅳ4、不同的二叉搜索树(卡特兰数) 1、一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#x…

IC 卡技术在生活中的应用

在现代科技高速发展的时代&#xff0c;IC 卡技术已经深入到我们生活的各个角落。它以其便捷、高效和安全的特点&#xff0c;为我们的生活带来了诸多便利。 IC 卡广泛应用于公共交通领域&#xff0c;让我们的出行变得更加顺畅。使用公交卡&#xff0c;只需轻轻一刷&#…

vue3 + ts 快速入门(全)

文章目录 学习链接1. Vue3简介1.1. 性能的提升1.2.源码的升级1.3. 拥抱TypeScript1.4. 新的特性 2. 创建Vue3工程2.1. 基于 vue-cli 创建2.2. 基于 vite 创建&#xff08;推荐&#xff09;vite介绍创建步骤项目结构安装插件项目结构总结 2.3. 一个简单的效果Person.vueApp.vue …

数字电路-5路呼叫显示电路和8路抢答器电路

本内容涉及两个电路&#xff0c;分别为5路呼叫显示电路和8路抢答器电路&#xff0c;包含Multisim仿真原文件&#xff0c;为掌握FPGA做个铺垫。紫色文字是超链接&#xff0c;点击自动跳转至相关博文。持续更新&#xff0c;原创不易&#xff01; 目录&#xff1a; 一、5路呼叫显…

Android BINDER是干嘛的?

1.系统架构 2.binder 源码位置&#xff1a; 与LINUX传统IPC对比

【迅投qmt系列】4、获取数据的方式

获取数据是进行策略回测、实时执行的前提&#xff0c;不同的场景下&#xff0c;有相对合适的数据获取方式。 1、只取历史数据 这个场景的内容一般是将历史数据下载下来后&#xff0c;再将数据用于其他用途。因为对效率没有多少要求&#xff0c;代码最简单&#xff0c;它将qmt…

【数学】高斯-约旦消元

前置知识 高斯消元 高斯-约旦消元 和高斯消元一样&#xff0c;高斯-约旦消元也是通过加减消元来化简方程。两者之间的不同在于&#xff0c;高斯-约旦消元会将系数矩阵消成形如 A ′ [ a 1 , 1 ′ b 1 ′ a 2 , 2 ′ b 2 ′ ⋱ ⋮ a n , n ′ b n ′ ] A\begin{bmatrix}a_{1…

题目:吃奶酪

问题描述&#xff1a; 解题思路&#xff1a; 枚举每种吃奶酪顺序&#xff0c;并计算其距离&#xff0c;选择最小的距离即答案。v数组&#xff1a;记录顺序。 注意点&#xff1a;1. 每次用于min的s需要重置为0。 2. 实数包括小数&#xff0c;所以结构体内x,y为double类型。 3. 第…