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

news2024/11/23 16:34:10

文章目录

  • 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.coloradmin.cn/o/1640923.html

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

相关文章

视频编辑软件pitivi基本功之将三个相关视频合并成一个视频

视频编辑软件pitivi基本功之将三个相关视频合并成一个视频 一、素材来源&#xff1a;网站下载 到http://cpc.people.com.cn/GB/67481/435238/437822/437828/437900/index.html下载以下三个视频&#xff0c;鼠标右击视频——另存视频为 庆祝中国共产党成立100周年大会即将开始—…

深度学习:基于TensorFlow、Keras,使用长短期记忆神经网络模型(LSTM)对Microsoft股票进行预测分析

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

R语言数据探索和分析7-使用随机森林模型对中国GDP及其影响因素分析

一、研究背景和意义 国内生产总值&#xff08;GDP&#xff09;是宏观经济领域中最为关注的经济统计数据之一&#xff0c;它反映了一个国家或地区在一定时期内所创造的所有最终商品和服务的总价值。GDP的增长率不仅仅是一个国家经济健康状况的关键指标&#xff0c;还直接关系到…

Web前端一套全部清晰 ⑥ day4 CSS.1 基础选择器、文字控制属性

后来的我不在抱怨 所有的事与愿违都是我能力或者判断力不足 仅此而已 —— 24.5.1 一、CSS定义 1. 将CSS放在html文件的<style>标签中 层叠样式表(Cascading style Sheets&#xff0c;缩写为 CSS)&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现(美…

软件应用开发安全设计指南

1.1 应用系统架构安全设计要求 设计时要充分考虑到系统架构的稳固性、可维护性和可扩展性&#xff0c;以确保系统在面对各种安全威胁时能够稳定运行。 在设计系统架构时&#xff0c;要充分考虑各种安全威胁&#xff0c;如DDoS攻击、SQL注入、跨站脚本攻击&#xff08;XSS&…

Github 2024-05-03 Java开源项目日报 Top9

根据Github Trendings的统计,今日(2024-05-03统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9Kotlin项目1C++项目1libGDX: 跨平台Java游戏开发框架 创建周期:4284 天开发语言:Java, C++协议类型:Apache License 2.0Star数量:2…

如何在Android设备上恢复丢失的照片

Android手机或平板电脑上的照片丢失了&#xff1f;不要惊慌&#xff0c;您也许可以恢复它们。 由于我们的大量数据和日常生活都存储在一台设备上&#xff0c;有时将所有照片存储在本地的 Android 智能手机或平板电脑上可能是一项冒险的工作。无论是通过事故&#xff08;损坏、…

【JVM】从硬件层面和应用层面的有序性和可见性,到Java的volatile和synchronized

Java的关键字volatile保证了有序性和可见性&#xff0c;这里我试着从底层开始讲一下有序性和可见性。 一&#xff0c;一致性 数据如果同时被两个cpu读取了&#xff0c;如何保证数据的一致性&#xff1f;或者换句话说&#xff0c;cpu1改了数据&#xff0c;cpu2的数据就成了无效…

【C++】深入剖析C++11 initializer_list 新的类功能 可变模板参数

目录 一、std::initializer_list 1、std::initializer_list是什么类型 2、std::initializer_list 的应用场景 ①给自定义容器赋值 ② 传递同类型的数据集合 二、新的类功能 1、默认成员函数 2、关键字default 3、关键字delete 三、可变参数模板 一、std::initialize…

C++仿函数周边及包装器

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

RunnerGo四月更新:强化UI自动化测试与UI录制插件功能

RunnerGo最近更新的 UI自动化测试和UI录制插件可以让测试人员更高效地布置UI自动化场景。这次优化升级的插件录制能力&#xff0c;可以更准确的定位元素并执行步骤&#xff0c;并增加了局部截图功能&#xff0c;准确查看定位的元素位置等。 UI插件V2.0介绍 接下来&#xff0c;让…

python基础算法题0502

数字反转 无论是字符串反转还是数字反转&#xff0c;其实都一样。 需求 代码 class Solution:def reverse(self, x: int) -> int:if 0 < x < 2 ** 31 - 1:m str(x)[::-1]if int(m)<2**31-1:return int(m)else:return 0if 0 > x > -2 ** 31:y -xn str(y…

2.6Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3-基础-Vue生命周期

在使用vue进行日常开发中&#xff0c;我们总有这样的需求&#xff0c;想在页面刚一加载出这个表格组件时&#xff0c;就发送请求去后台拉取 数据&#xff0c;亦或者想在组件加载前显示个loading图&#xff0c;当组件加载出来就让这个loading图消失等等这样或那样的需求。 要实…

Java_JVM_JVMs

JVM 官方文档说明文档目录 官方文档 JVM Specification 说明 以Java SE 17为标准 文档目录 2&#xff1a;JVM 结构 class文件数据类型 基本数据类型引用数据类型 运行时数据区 栈帧 其他内容 对象的表示浮点数运算特殊方法 初始化方法【实例、类】多态方法 3&#xff…

【多变量控制系统 Multivariable Control System】(1)DSM:术语、基本公式和MATLAB仿真【新加坡南洋理工大学】

说明&#xff1a; 题目版权归校方所有&#xff0c;仅供学习和参考使用。 DSM Control DSM Direct Synthesis Method Process Model Closed-Loop Transfer Function 基本公式 &#xff08;1&#xff09;输入、输出关系 &#xff08;2&#xff09;控制器表示 MatLab仿真…

如何在Mac上恢复格式化硬盘的数据?

“嗨&#xff0c;我格式化了我的一个Mac硬盘&#xff0c;而没有使用Time Machine备份数据。这个硬盘被未知病毒感染了&#xff0c;所以我把它格式化为出厂设置。但是&#xff0c;我忘了备份我的文件。现在&#xff0c;我想恢复格式化的硬盘驱动器并恢复我的文档&#xff0c;您能…

Go协程的底层原理(图文详解)

为什么要有协程 什么是进程 操作系统“程序”的最小单位进程用来占用内存空间进程相当于厂房&#xff0c;占用工厂空间 什么是线程 进程如果比作厂房&#xff0c;线程就是厂房里面的生产线&#xff1a; 每个进程可以有多个线程线程使用系统分配给进程的内存&#xff0c;线…

OpenWRT有线桥接部署教程

前言 之前咱们讲到OpenWRT部署WAN实现PPPoE拨号上网和自动获取IP模式上网的办法&#xff1a; OpenWRT设置PPPoE拨号教程 OpenWRT设置自动获取IP&#xff0c;作为二级路由器 这一次&#xff0c;咱们尝试用OpenWRT有线桥接上一级路由器的教程。 可能有小伙伴敏锐地发现了&am…

15、ESP32 Wifi

ESP32 的 WIFI 功能是模块内置的&#xff0c;通过 ESP32 的基础库调用一些函数就可以轻松使用它。 Wifi STA 模式&#xff1a; 让 ESP32 连接附近 WIFI&#xff0c;可以上网访问数据。 // 代码显示搜索连接附近指定的 WIFI // 通过 pin 按键可断开连接#include <WiFi.h>…

Docker - 修改服务的端口

1. 测试 新建一个httpd服务 docker run -itd -p 1314:80 --name test -h test httpd 2. 先停止容器和 docke r服务 docker stop test #停止容器3. 修改配置 cd /var/lib/docker/containers ls 找到需要修改的 cd 1fc55f0d24014217cff68c9a417ca46cf50312caa5c9e6bb24085126…