理解位图算法:使用 C++ 实现高效数据查重

在处理海量数据时,我们常常需要检查某个元素是否已经存在于集合中。传统的方法如哈希表或集合容器虽然有效,但在数据量极大的情况下会占用大量内存。这时,位图算法 (Bitmap) 就成为了一种非常高效的解决方案。本文将通过分析一段使用位图算法的 C++ 代码,深入探讨这种算法的原理和实现。

位图算法基本原理

位图算法的核心思想是使用一个二进制位 (bit) 来表示某个元素是否存在。每个位对应一个特定的值,如果该值存在,则对应的位被置为 1,否则为 0。这种方法的优势在于它能极大地节省存储空间。例如,使用一个 64 位的long long类型变量,我们可以表示 64 个不同的值,而不是像传统数组那样每个元素占用一个完整的存储单元。

代码实现分析

让我们来分析这段使用位图算法的 C++ 代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<memory>
using namespace std;
typedef long long LL;
int main()
{int num;//元素个数;cin >> num;LL MAX = 0;vector<LL>q;for (int i = 0; i < num; i++){LL sum;cin >> sum;MAX = max(MAX, abs(sum));q.push_back(sum);}const LL len = MAX / 64 + 1;//位图算法,长度由最大值的绝对值/容器数据类型字节大小,long long是64字节的;//LL arr[len]由于len是变量,所以这里没办法在栈上定义了unique_ptr<LL[]>arr(new LL[len]);unique_ptr<LL[]>brr(new LL[len]);LL mod = 64;for (auto it : q){LL sum = 1;if (it > 0){int idx = it / mod;LL num = it % mod;if (arr[idx] >> num)continue;else arr[idx] |= (sum << num);}else{int idx = abs(it) / mod;LL num = abs(it) % mod;if (brr[idx] >> num)continue;else brr[idx] |= (sum << num);}}
}

代码功能解析

这段代码的主要功能是读取一组整数,然后使用位图算法来标记每个数是否存在。代码处理了正数和负数两种情况,下面是详细的步骤解析:

  1. 输入处理与最大值计算

    • 首先读取元素的数量num
    • 依次读取每个元素,并计算它们的绝对值的最大值MAX
    • 将所有元素存储在向量q
  2. 位图数组初始化

    • 计算位图数组的长度len,公式为MAX / 64 + 1
    • 使用unique_ptr动态分配两个long long类型的数组arrbrr
    • arr用于存储正数的位图
    • brr用于存储负数的位图
  3. 位图操作

    • 遍历每个元素,根据其正负分别处理
    • 对于正数,计算其在位图数组中的索引idx和位偏移num
    • 使用位运算检查该位是否已被设置,如果未设置则设置该位
    • 负数的处理类似,但使用brr数组

位运算详解

在位图算法中,位运算是核心操作。让我们详细解释代码中的位运算部分:

计算索引和位偏移

int idx = it / mod;  // 计算元素所在的数组索引
LL num = it % mod;   // 计算元素在该索引位置的位偏移

检查位是否已设置

if (arr[idx] >> num) continue;

这行代码将arr[idx]右移num位,如果结果不为 0,则表示该位已被设置。

设置位

arr[idx] |= (sum << num);

这行代码将 1 左移num位,然后使用按位或操作将对应位置为 1。

位图算法的优势与应用场景

位图算法的主要优势包括:

  • 空间效率极高:每个值只占用一个位,相比传统方法节省大量内存
  • 操作速度快:位运算在现代计算机上非常高效
  • 实现简单:核心逻辑只需要基本的位运算

位图算法适用于以下场景:

  • 数据查重:检查元素是否已经存在
  • 数据排序:可以在位图上进行高效的排序操作
  • 数据统计:统计某个范围内数据的分布情况

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

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

相关文章

数学复习笔记 12

前言 现在做一下例题和练习题。矩阵的秩和线性相关。另外还要复盘前面高数的部分的内容。奥&#xff0c;之前矩阵的例题和练习题&#xff0c;也没有做完&#xff0c;行列式的例题和练习题也没有做完。累加起来了。以后还是得学一个知识点就做一个部分的内容&#xff0c;日拱一…

1-10 目录树

在ZIP归档文件中&#xff0c;保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时&#xff0c;可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。 输入格式: 输入首先给出正整数N&#xff08;≤104&#xff09;…

Python爬虫实战:研究 RPC 远程调用机制,实现逆向解密

1. 引言 在网络爬虫技术的实际应用中,目标网站通常采用各种加密手段保护其数据传输和业务逻辑。这些加密机制给爬虫开发带来了巨大挑战,传统的爬虫技术往往难以应对复杂的加密算法。逆向解密作为一种应对策略,旨在通过分析和破解目标网站的加密机制,获取原始数据。 然而,…

debugfs:Linux 内核调试的利器

目录 一、什么是 debugfs&#xff1f;二、debugfs 的配置和启用方式2.1 内核配置选项2.2 挂载 debugfs2.3 Android 系统中的 debugfs 三、debugfs 的典型应用场景3.1 调试驱动开发3.2 内核子系统调试3.3 性能分析 四、常见 debugfs 子目录与功能示例4.1 /sys/kernel/debug/trac…

lua 作为嵌入式设备的配置语言

从lua的脚本中获取数据 lua中栈的索引 3 | -1 2 | -2 1 | -3 可以在lua的解释器中加入自己自定的一些功能,其实没啥必要,就是为了可以练习下lua

棋牌室台球室快速接入美团团购接口

北极星平台从2024年12月份开始慢慢关闭&#xff0c;现在很多开发者反馈北极星token已经不能刷新了&#xff0c;全部迁移到美团团购综合平台。 申请这个平台要求很高 1、保证金费用要15万起步 2、平台必须是二级等保和安全产品 &#xff0c;一个二级等保费用10万起步 所以很多…

开源轻量级地图解决方案leaflet

Leaflet 地图&#xff1a;开源轻量级地图解决方案 Leaflet 是一个开源的 JavaScript 库&#xff0c;用于在网页中嵌入交互式地图。它以轻量级、灵活性和易用性著称&#xff0c;适用于需要快速集成地图功能的项目。以下是关于 Leaflet 的详细介绍和使用指南。 1. Leaflet 的核心…

一个批量文件Dos2Unix程序(Microsoft Store,开源)1.1.0 编码检测和预览

之前的版本是个意思意思&#xff0c;验证商店发布的&#xff08;其实是我以前自己用的工具&#xff09;&#xff0c;这次把格式检查和转换都做上了&#xff0c;功能应该差不多了&#xff0c;还有一些需要小改进的地方。 因为还没什么用户嘛&#xff0c;还是保持全功能免费试用。…

特征提取:如何从不同模态中获取有效信息?

在多模态学习中&#xff0c;不同模态&#xff08;文本、图像、语音、视频、传感器数据等&#xff09;所携带的信息丰富且互补。但不同模态的数据结构、表示空间、时空分布截然不同&#xff0c;因此&#xff0c;如何对各模态进行高效、有效的特征提取&#xff0c;是整个多模态学…

Go语言爬虫系列教程 实战项目JS逆向实现CSDN文章导出教程

爬虫实战&#xff1a;JS逆向实现CSDN文章导出教程 在这篇教程中&#xff0c;我将带领大家实现一个实用的爬虫项目&#xff1a;导出你在CSDN上发布的所有文章。通过分析CSDN的API请求签名机制&#xff0c;我们将绕过平台限制&#xff0c;获取自己的所有文章内容&#xff0c;并以…

交叉熵损失函数,KL散度, Focal loss

交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09; 交叉熵损失函数&#xff0c;涉及两个概念&#xff0c;一个是损失函数&#xff0c;一个是交叉熵。 首先&#xff0c;对于损失函数。在机器学习中&#xff0c;损失函数就是用来衡量我们模型的预测结果与真实结果之间…

149.WEB渗透测试-MySQL基础(四)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;148.WEB渗透测试-MySQL基础&#xff08;三&#xff09; 非关系型数据库&#xff1a; &a…

c/c++中程序内存区域的划分

c/c程序内存分配的几个区域&#xff1a; 1.栈区&#xff1a;在执行函数时&#xff0c;函数内局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结束时这些存储单元自动被释放&#xff0c;栈内存分配运算内置于处理器的指令集中&#xff0c;效率很高但是分配的内存容量有…

构建稳定的金字塔模式生态:从自然法则到系统工程

在自然界中&#xff0c;金字塔结构广泛存在于生态系统之中&#xff0c;表现为营养级能量金字塔、生物量金字塔和数量金字塔等形式。这种结构不仅形象地描述了生态能量流转的规律&#xff0c;也体现出生态系统中“稳定性”与“层级性”的天然法则。在现代软件架构、企业组织、平…

Vue 3.0双向数据绑定实现原理

Vue3 的数据双向绑定是通过响应式系统来实现的。相比于 Vue2&#xff0c;Vue3 在响应式系统上做了很多改进&#xff0c;主要使用了 Proxy 对象来替代原来的 Object.defineProperty。本文将介绍 Vue3 数据双向绑定的主要特点和实现方式。 1. 响应式系统 1.1. Proxy对象 Vue3 …

TIP-2021《SRGAT: Single Image Super-Resolution With Graph Attention Network》

推荐深蓝学院的《深度神经网络加速&#xff1a;cuDNN 与 TensorRT》&#xff0c;课程面向就业&#xff0c;细致讲解CUDA运算的理论支撑与实践&#xff0c;学完可以系统化掌握CUDA基础编程知识以及TensorRT实战&#xff0c;并且能够利用GPU开发高性能、高并发的软件系统&#xf…

大语言模型与多模态模型比较

一、核心差异&#xff1a;输入数据类型与模态融合 输入数据类型 LLM&#xff1a;仅处理文本数据&#xff0c;例如文本分类、机器翻译、问答等任务&#xff0c;通过大规模语料库学习语言规律。 LMM&#xff1a;支持文本、图像、音频、视频等多种模态输入&#xff0c;例如根据图…

Apache HttpClient 5 用法-Java调用http服务

Apache HttpClient 5 核心用法详解 Apache HttpClient 5 是 Apache 基金会推出的新一代 HTTP 客户端库&#xff0c;相比 4.x 版本在性能、模块化和易用性上有显著提升。以下是其核心用法及最佳实践&#xff1a; 一、添加依赖 Maven 项目&#xff1a; <dependency><…

基于 Spark 的流量统计

一、引言 在互联网行业&#xff0c;流量统计是分析网站或应用用户行为、评估业务表现、优化资源分配以及制定营销策略的关键环节。借助 Apache Spark 强大的分布式数据处理能力&#xff0c;我们可以高效地对大规模的流量数据进行统计分析&#xff0c;获取有价值的洞察。本文将…

Python模块化编程进阶指南:从基础到工程化实践

一、模块化编程核心原理与最佳实践 1.1 模块化设计原则 根据企业级项目实践&#xff0c;模块化开发应遵循以下核心原则&#xff1a; ​​单一职责原则​​&#xff1a;每个模块只承担一个功能域的任务&#xff08;如用户认证模块独立于日志模块&#xff09;​​接口隔离原则…