基于C#实现Bitmap算法

news2024/10/2 12:24:36

在所有具有性能优化的数据结构中,我想大家使用最多的就是 hash 表,是的,在具有定位查找上具有 O(1)的常量时间,多么的简洁优美,但是在特定的场合下:
①:对 10 亿个不重复的整数进行排序。
②:找出 10 亿个数字中重复的数字。
当然我只有普通的服务器,就算 2G 的内存吧,在这种场景下,我们该如何更好的挑选数据结构和算法呢?

一、问题分析

这年头,大牛们写的排序算法也就那么几个,首先我们算下放在内存中要多少 G:
(10 亿 * 32)/(102410241024*8)=3.6G,可怜的 2G 内存直接爆掉,所以各种神马的数据结构都玩不起来了,当然使用外排序还是可以解决问题的,由于要走 IO 所以暂时剔除,因为我们要玩高性能,无望后我们想想可不可以在二进制位上做些手脚?
比如我要对{1,5,7,2}这四个 byte 类型的数字做排序,该怎么做呢?我们知道 byte 是占 8 个 bit 位,其实我们可以将数组中的值作为 bit 位的 key,value 用”0,1“来标识该 key 是否出现过?下面看图:
image.png
从图中我们精彩的看到,我们的数组值都已经作为 byte 中的 key 了,最后我只要遍历对应的 bit 位是否为 1 就可以了,那么自然就成有序数组了。
可能有人说,我增加一个 13 怎么办?很简单,一个字节可以存放 8 个数,那我只要两个 byte 就可以解决问题了。
image.png
可以看出我将一个线性的数组变成了一个 bit 位的二维矩阵,最终我们需要的空间仅仅是:3.6G/32=0.1G 即可,要注意的是 bitmap 排序不是 N 的,而是取决于待排序数组中的最大值,在实际应用上关系也不大,比如我开 10 个线程去读 byte 数组,那么复杂度为:O(Max/10)。

二、代码

我想 bitmap 的思想大家都清楚了,这一次又让我们见证了二进制的魅力,当然这些移位都是位运算的工作了,熟悉了你就玩转了。

1、Clear 方法(将数组的所有 bit 位置 0)

比如要将当前 4 对应的 bit 位置 0 的话,只需要 1 左移 4 位取反与 B[0] & 即可。
image.png

 #region 初始化所用的bit位为0
 /// <summary>
 /// 初始化所用的bit位为0
 /// </summary>
 /// <param name="i"></param>
 static void Clear(byte i)
 {
     //相当于 i%8 的功能
     var shift = i & 0x07;

     //计算应该放数组的下标
     var arrindex = i >> 3;

     //则将当前byte中的指定bit位取0,&后其他对方数组bit位必然不变,这就是 1 的妙用
     var bitPos = ~(1 << shift);

     //将数组中的指定bit位置一  “& 操作”
     a[arrindex] &= (byte)(bitPos);
 }
 #endregion

2、Add 方法(将 bit 置 1 操作)

同样也很简单,要将当前 4 对应的 bit 位置 1 的话,只需要 1 左移 4 位与 B[0] | 即可。
image.png

 #region 设置相应bit位上为1
 /// <summary>
 /// 设置相应bit位上为1
 /// </summary>
 /// <param name="i"></param>
 static void Add(byte i)
 {
     //相当于 i%8 的功能
     var shift = i & 0x07;

     //计算应该放数组的下标
     var arrindex = i >> 3;

     //将byte中的 1 移动到i位
     var bitPos = 1 << shift;

     //将数组中的指定bit位置一  “| 操作”
     a[arrindex] |= (byte)bitPos;
 }
 #endregion

3、Contain 方法(判断当前 bit 位是否是 1)

如果看懂了 Clear 和 Add,我相信最后一个方法已经不成问题了。

 #region 判断当前的x在数组的位中是否存在
 /// <summary>
 ///判断当前的x在数组的位中是否存在
 /// </summary>
 /// <param name="i"></param>
 /// <returns></returns>
 static bool Contain(byte i)
 {
     var j = a[i >> 3] & (1 << (i & 0x07));

     if (j == 0)
         return false;
     return true;
 }
 #endregion

最后上总的代码:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Diagnostics;
 using System.Threading;
 using System.IO;
 
 namespace ConsoleApplication2
 {
     public class Program
     {
         static byte n = 7;
 
         static byte[] a;
 
         public static void Main()
         {
             //节省空间的做法
             a = new byte[(n >> 3) + 1];
 
             for (byte i = 0; i < n; i++)
                 Clear(i);
 
             Add(4);
             Console.WriteLine("插入4成功!");
 
             var s = Contain(4);
 
             Console.WriteLine("当前是否包含4:{0}", s);
 
             s = Contain(5);
 
             Console.WriteLine("当前是否包含5:{0}", s);
 
             Console.Read();
         }
 
         #region 初始化所用的bit位为0
         /// <summary>
         /// 初始化所用的bit位为0
         /// </summary>
         /// <param name="i"></param>
         static void Clear(byte i)
         {
             //相当于 i%8 的功能
             var shift = i & 0x07;
 
             //计算应该放数组的下标
             var arrindex = i >> 3;
 
             //则将当前byte中的指定bit位取0,&后其他对方数组bit位必然不变,这就是 1 的妙用
             var bitPos = ~(1 << shift);
 
             //将数组中的指定bit位置一  “& 操作”
             a[arrindex] &= (byte)(bitPos);
         }
         #endregion
 
         #region 设置相应bit位上为1
         /// <summary>
         /// 设置相应bit位上为1
         /// </summary>
         /// <param name="i"></param>
         static void Add(byte i)
         {
             //相当于 i%8 的功能
             var shift = i & 0x07;
 
             //计算应该放数组的下标
             var arrindex = i >> 3;
 
             //将byte中的 1 移动到i位
             var bitPos = 1 << shift;
 
             //将数组中的指定bit位置一  “| 操作”
             a[arrindex] |= (byte)bitPos;
         }
         #endregion
 
         #region 判断当前的x在数组的位中是否存在
         /// <summary>
         ///判断当前的x在数组的位中是否存在
         /// </summary>
         /// <param name="i"></param>
         /// <returns></returns>
         static bool Contain(byte i)
         {
             var j = a[i >> 3] & (1 << (i & 0x07));
 
             if (j == 0)
                 return false;
             return true;
         }
         #endregion
     }
 }

image.png

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

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

相关文章

2023年度openGauss标杆应用实践案例征集

标杆应用实践案例征集 2023 openGauss 数据库作为企业IT系统的核心组成部分&#xff0c;是数字基础设施建设的关键&#xff0c;是实现数据安全稳定的保障。openGauss顺应开源发展趋势&#xff0c;强化核心技术突破&#xff0c;着力打造自主根社区&#xff0c;携手产业伙伴共同…

手把手教你通过CODESYS V3进行PLC编程(二)

教程背景 在上一期教程中&#xff0c;我们已经完成了控制器设备的连接和配置。接下来的教程将继续以宏集MC-Prime为例&#xff0c;假设控制器已经配置并连接到开发者的PC上&#xff0c;为您演示如何为控制器安装合适的CODESYS V3版本并创建第一个程序。 一、安装CODESYS &…

冷链运输车辆GPS定位及温湿度管理案例

1.项目背景 项目名称&#xff1a;山西冷链运输车辆GPS定位及温湿度管理案例 项目需求&#xff1a;随着经济发展带动物流行业快速发展&#xff0c;运输规模逐步扩大&#xff0c;集团为了适应高速发展的行业现象&#xff0c;物流管理系统的完善成了现阶段发展的重中之重。因此&…

FDG6306P PowerTrench® MOSFET P沟道 特点及其应用详解

关于PowerTrench MOSFET&#xff1f; 它是一种MOS场效应晶体管&#xff0c;可以提高系统效率和功率密度。该技术采用了屏蔽栅极技术&#xff0c;可以减少开关损耗和导通损耗&#xff0c;从而提高了系统效率。此外&#xff0c;PowerTrench MOSFET还具有低导通电阻和高开关速度的…

史上最细教程-一台服务器上搭建2个MySQL实例

史上最细教程-一台服务器上搭建2个MySQL实例 文章目录 史上最细教程-一台服务器上搭建2个MySQL实例环境准备&#xff1a;操作步骤&#xff1a;1.安装MySQL2.配置搭建3306、3307实例3.初始化3306、3307实例、远程连接访问支持 环境准备&#xff1a; 服务器&#xff1a;阿里云Ce…

斯坦福大学引入FlashFFTConv来优化机器学习中长序列的FFT卷积

斯坦福大学的FlashFFTConv优化了扩展序列的快速傅里叶变换(FFT)卷积。该方法引入Monarch分解&#xff0c;在FLOP和I/O成本之间取得平衡&#xff0c;提高模型质量和效率。并且优于PyTorch和FlashAttention-v2。它可以处理更长的序列&#xff0c;并在人工智能应用程序中打开新的可…

【网络】数据链路层协议

数据链路层协议 一、链路层解决的问题二、以太网协议1、局域网技术2、令牌环网&#xff08;了解&#xff09;3、以太网通信原理4、 MAC地址5、以太网帧格式6、碰撞避免7、最大传输单元MTU 二、ARP协议1、ARP数据的格式2、ARP协议的工作流程3、ARP缓存表4、ARP协议中的一些问题7…

力控软件与多台PLC之间ModbusTCP/IP无线通信

Modbus TCP/IP 是对成熟的 Modbus 协议的改编&#xff0c; 因其开放性、简单性和广泛接受性而在工业自动化系统中发挥着举足轻重的作用。它作为连接各种工业设备的通用通信协议&#xff0c;包括可编程逻辑控制器 (PLC)、远程终端单元 (RTU) 和传感器。它提供标准化的 TCP 接口&…

从零开始,用Docker-compose打造SkyWalking、Elasticsearch和Spring Cloud的完美融合

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 "从零开始&#xff0c;用Docker-compose打造SkyWalking、Elasticsearch和Spring Cloud的完美融合 前言准备工作编写docker-compose.yml文件为什么使用本机ip为什么skywa…

VL06O报表添加增强字段

业务描述 用户需要在VL06O事务代码下进行批量交货过账&#xff0c;现有的筛选条件不太适用当前公司的业务&#xff0c;需要在报表中新增三个交货单增强字段&#xff0c;方便其筛选&#xff08;选择屏幕没有加&#xff0c;用户在报表里用标准按钮功能自己筛选&#xff09; 效果…

百战python01-初识python_turtle绘图

文章目录 简介练习1.简易的进度条学习使用turtle在屏幕上绘制图形注:需要对python有基本了解,可查看本作者python基础专栏,有任何问题欢迎私信或评论(本专栏每章内容都将不定期进行内容扩充与更新) 简介 python简介及方向+pycharm安装使用请转 练习 注:尝试练习。了解…

视频云存储EasyCVR平台国标接入获取通道设备未回复是什么原因?该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

Windows平台Unity下实现camera场景推送RTMP|轻量级RTSP服务|实时录像

技术背景 我们在对接Unity平台camera场景采集的时候&#xff0c;除了常规的RTMP推送、录像外&#xff0c;还有一些开发者&#xff0c;需要能实现轻量级RTSP服务&#xff0c;对外提供个拉流的RTSP URL。 目前我们在Windows平台Unity下数据源可采集到以下部分&#xff1a; 采集…

如何满足BMW EDI项目的PKT需求?

近期宝马BMW&#xff08;以下简称BMW&#xff09;在其部分供应商之间试点推进PKT项目&#xff0c;BMW为什么要启动 PKT 计划呢&#xff1f; 业务系统全面升级统一全球所有宝马工厂的流程 宝马内部的物流供货流程 近期BMW PKT需求主要针对其内部物流供货流程展开&#xff1a; …

linux下流媒体压力测试工具的使用

前言 因为领导要求做linux的推拉流时服务器压力测试&#xff0c;于是在网上找了找。一顿操作下来&#xff0c;发现很多软件盗用一款名为srs-bench的开源软件。 该代码仓库有详细的使用说明&#xff0c;而且可以在issues中找到可能会遇到的问题的解决办法 需要下载该仓库的源…

网页小游戏的开发流程

网页小游戏的开发流程可以分为几个关键步骤。这只是一个一般性的流程概述&#xff0c;具体的步骤可能会根据项目的规模和要求而有所不同。此外&#xff0c;还要考虑法律和版权问题&#xff0c;确保你的游戏开发过程是合法的。下面是一个简要的概述&#xff0c;希望对大家有所帮…

Centos Download

前言 CentOS Linux 是一个社区支持的发行版&#xff0c;源自 CentOS git for Red Hat Enterprise Linux &#xff08;RHEL&#xff09; 上免费提供给公众的源代码。因此&#xff0c;CentOS Linux 的目标是在功能上与 RHEL 兼容。CentOS 计划主要更改组件以删除上游供应商的品牌…

【QML】StackView上层页面半透明,显示下层页面

1、 应用场景 有时候需要模拟弹窗效果&#xff0c;需要下层的页面半透明显示。仅仅将上层页面背景设置为透明并不能实现这个效果&#xff0c;下层的页面依然被覆盖。Qt帮助文档中有如下代码&#xff0c;经测试有效果。 2、 代码 重点标记&#xff1a; 下层页面需要设置这个…

220V转12V固定输出12V非隔离芯片WT5106WT5105

220V转12V固定输出12V非隔离芯片WT5106WT5105 今天给大家介绍一款实用芯片&#xff0c;WT5106。它是一款高效率高精度的非隔离降压开关电源恒压控制驱动芯片。 WT5106适用于85VAC~265VAC全范围输入电压的非隔离Buck、Buckboost拓扑结构&#xff0c;小家电、电机驱动、继电器驱…

Django框架环境的搭建(图文详解)

目录 day01 Web框架和Django基础 1.web框架底层 1.1 网络通信​编辑 1.2 常见软件架构 1.3 手撸web框架 2.web框架 2.1 wsgiref 2.2 werkzeug 2.3 各框架的区别 3.快速上手django框架 3.1 安装 3.2 命令行 3.3 Pycharm 4.虚拟环境 4.1 创建虚拟环境 - 命令行 4…